without understanding run method ejemplos create await async c# asynchronous async-await

understanding - task.run c#



Hacer implementaciones de interfaz asincrónicas (2)

Actualmente estoy intentando hacer mi aplicación usando algunos métodos Async. Todo mi IO se realiza a través de implementaciones explícitas de una interfaz y estoy un poco confundido acerca de cómo hacer que las operaciones sean asincrónicas.

Cuando veo cosas, tengo dos opciones en la implementación:

interface IIO { void DoOperation(); }

OPCIÓN1: realice una implementación implícita asincrónica y espere el resultado en la implementación implícita.

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 }

OPCIÓN2: realice la implementación explícita asincrónica y espere la tarea desde la implementación implícita.

class IOAsyncImplementation : IIO { private Task DoOperationAsync() { return new Task(() => { //DO ALL THE HEAVY LIFTING!!! }); } #region IIOAsync Members async void IIO.DoOperation() { await DoOperationAsync(); } #endregion }

¿Alguna de estas implementaciones es mejor que la otra o hay otro camino por recorrer en el que no estoy pensando?


Ninguna de estas opciones es correcta. Está intentando implementar una interfaz síncrona de forma asíncrona. No hagas eso. El problema es que cuando DoOperation() vuelve, la operación no estará completa todavía. Peor aún, si ocurre una excepción durante la operación (que es muy común en las operaciones de E / S), el usuario no tendrá la oportunidad de manejar esa excepción.

Lo que debe hacer es modificar la interfaz para que sea asincrónica:

interface IIO { Task DoOperationAsync(); // note: no async here } class IOImplementation : IIO { public async Task DoOperationAsync() { // perform the operation here } }

De esta forma, el usuario verá que la operación es async y podrá await . Esto también obliga a los usuarios de su código a cambiar a async , pero eso es inevitable.

Además, supongo que usar StartNew() en su implementación es solo un ejemplo, no debería necesitar eso para implementar IO asíncrona. (Y la new Task() es aún peor, eso ni siquiera funcionará, porque usted no Start() la Task ).


Una mejor solución es introducir otra interfaz para operaciones asincrónicas. La nueva interfaz debe heredar de la interfaz original.

Ejemplo:

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); } }

PS Rediseña tus operaciones asíncronas para que devuelvan Tarea en lugar de nulas, a menos que realmente tengas que devolver el vacío.