Создание асинхронных реализаций интерфейса
В настоящее время я пытаюсь сделать Мои приложения, используя некоторые асинхронные методы. Все мои IO выполняются через явные реализации интерфейса, и я немного смущен тем, как сделать операции асинхронными.
как я вижу, у меня есть два варианта реализации:
interface IIO
{
    void DoOperation();
}
OPTION1: Выполните неявную реализацию async и дождитесь результата в неявной реализации.
class IOImplementation : IIO
{
     async void DoOperation()
    {
        await Task.Factory.StartNew(() =>
            {
                //WRITING A FILE OR SOME SUCH THINGAMAGIG
            });
    }
    #region IIO Members
    void IIO.DoOperation()
    {
        DoOperation();
    }
    #endregion
}
OPTION2: Сделать явным реализация асинхронна и ожидает задачи от неявной реализации.
class IOAsyncImplementation : IIO
{
    private Task DoOperationAsync()
    {
        return new Task(() =>
            {
                //DO ALL THE HEAVY LIFTING!!!
            });
    }
    #region IIOAsync Members
    async void IIO.DoOperation()
    {
        await DoOperationAsync();
    }
    #endregion
}
является ли одна из этих реализаций лучше, чем другая, или есть другой способ пойти, о котором я не думаю?
2 ответа:
ни один из этих вариантов правильный. Вы пытаетесь реализовать синхронный интерфейс асинхронно. Не делай этого. Проблема в том, что когда
DoOperation()возвращает, операция еще не будет завершена. Хуже того, если во время операции происходит исключение (что очень часто встречается с операциями ввода-вывода), у пользователя не будет возможности справиться с этим исключением.то, что вам нужно сделать, это изменить интерфейс, так что это асинхронный:
interface IIO { Task DoOperationAsync(); // note: no async here } class IOImplementation : IIO { public async Task DoOperationAsync() { // perform the operation here } }таким образом, пользователь увидит, что операция
asyncи они смогутawaitего. Это также в значительной степени заставляет пользователей вашего кода переключаться наasync, но это неизбежно.кроме того, я полагаю, используя
StartNew()в вашей реализации это просто пример, вам не нужно, чтобы реализовать асинхронный ввод-вывод. (Иnew Task()еще хуже, что даже не будет работать, потому что вы неStart()theTask.)
лучшим решением является введение другого интерфейса для асинхронных операций. Новый интерфейс должен наследовать от исходного интерфейса.
пример:
interface IIO { void DoOperation(); } interface IIOAsync : IIO { Task DoOperationAsync(); } class ClsAsync : IIOAsync { public void DoOperation() { DoOperationAsync().GetAwaiter().GetResult(); } public async Task DoOperationAsync() { //just an async code demo await Task.Delay(1000); } } class Program { static void Main(string[] args) { IIOAsync asAsync = new ClsAsync(); IIO asSync = asAsync; Console.WriteLine(DateTime.Now.Second); asAsync.DoOperation(); Console.WriteLine("After call to sync func using Async iface: {0}", DateTime.Now.Second); asAsync.DoOperationAsync().GetAwaiter().GetResult(); Console.WriteLine("After call to async func using Async iface: {0}", DateTime.Now.Second); asSync.DoOperation(); Console.WriteLine("After call to sync func using Sync iface: {0}", DateTime.Now.Second); Console.ReadKey(true); } }С. П. Перепроектируйте свои асинхронные операции, чтобы они возвращали Task вместо void, если вы действительно не должны возвращать void.