without whenall practices method httpresponsemessage explained create best await async c# async-await

c# - whenall - Utilice una devolución de llamada asíncrona con Task.ContinueWith



task httpresponsemessage c# (3)

Al encadenar varias tareas con el método ContinueWith , su tipo de devolución será Task<T> mientras que T es el tipo de devolución del delegado / método pasado a ContinueWith .

Como el tipo de retorno de un delegado asíncrono es una Task , terminará con una Task<Task> y terminará esperando que el delegado asíncrono le devuelva la Task que se realiza después de la primera await .

Para corregir este comportamiento, debe usar la Task devuelta, incrustada en su Task<Task> . Utilice el método de extensión Unwrap para extraerlo.

Estoy tratando de jugar un poco con C # ''s async / await / continuewith. Mi objetivo es tener que tener 2 tareas que se ejecutan en paralelo, aunque la tarea es ejecutar una secuencia de acciones en orden. Para hacer eso, planeé tener una List<Task> que representa las 2 (o más) tareas que se ejecutan en paralelo, y usar ContinueWith con cada una de las Task Mi problema es que la devolución de llamada en continuar no parece ejecutarse mientras la lista de await taskList ya ha regresado.

Para resumir, aquí hay una muestra para ilustrar lo que espero que suceda:

class Program { static public async Task Test() { System.Console.WriteLine("Enter Test"); await Task.Delay(100); System.Console.WriteLine("Leave Test"); } static void Main(string[] args) { Test().ContinueWith( async (task) => { System.Console.WriteLine("Enter callback"); await Task.Delay(1000); System.Console.WriteLine("Leave callback"); }, TaskContinuationOptions.AttachedToParent).Wait(); Console.WriteLine("Done with test"); } }

La salida esperada sería

Enter Test Leave Test Enter callback Leave callback Done with test

Sin embargo, la salida es

Enter Test Leave Test Enter callback Done with test

¿Hay alguna manera de hacer que la tarea en la que se llama a ContinueWith se espere a que se complete la función proporcionada antes de que se considere como finalizada? es decir. .Wait esperará a que se completen ambas tareas, la original y la que devuelve ContinueWith


Cuando esté haciendo una programación async , debe esforzarse por reemplazar ContinueWith con await , como tal:

class Program { static public async Task Test() { System.Console.WriteLine("Enter Test"); await Task.Delay(100); System.Console.WriteLine("Leave Test"); } static async Task MainAsync() { await Test(); System.Console.WriteLine("Enter callback"); await Task.Delay(1000); System.Console.WriteLine("Leave callback"); } static void Main(string[] args) { MainAsync().Wait(); Console.WriteLine("Done with test"); } }

El código que utiliza await es mucho más limpio y fácil de mantener.

Además, no debe usar tareas principales / secundarias con tareas async (por ejemplo, AttachedToParent ). No fueron diseñados para trabajar juntos.


Me gustaría añadir mi respuesta para complementar la respuesta que ya ha sido aceptada. Dependiendo de lo que intente hacer, a menudo es posible evitar la complejidad adicional de los delegados asíncronos y las tareas envueltas. Por ejemplo, su código podría ser re-factorizado de esta manera:

class Program { static async Task Test1() { System.Console.WriteLine("Enter Test"); await Task.Delay(100); System.Console.WriteLine("Leave Test"); } static async Task Test2() { System.Console.WriteLine("Enter callback"); await Task.Delay(1000); System.Console.WriteLine("Leave callback"); } static async Task Test() { await Test1(); // could do .ConfigureAwait(false) if continuation context doesn''t matter await Test2(); } static void Main(string[] args) { Test().Wait(); Console.WriteLine("Done with test"); } }