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

c# - whenall - Llamando al método asíncrono en IEnumerable.Select



task httpresponsemessage c# (1)

Puedes resolver esto considerando los tipos en juego. Por ejemplo, MapToLocalObject , cuando se ve como una función asíncrona, se MapToLocalObject de R a L Pero si lo ve como una función síncrona, se asigna de R a Task<L> .

Task es un "futuro", por lo que la Task<L> se puede considerar como un tipo que producirá una L en algún momento en el futuro.

Así que puedes convertir fácilmente de una secuencia de R a una secuencia de Task<L> :

IEnumerable<Task<L>> mappingTasks = remoteItems.Select(remoteItem => MapToLocalObject(remoteItem));

Tenga en cuenta que existe una importante diferencia semántica entre este y su código original. El código original espera a que se asigne cada objeto antes de pasar al siguiente objeto; este código iniciará todas las asignaciones al mismo tiempo.

Su resultado es una secuencia de tareas, una secuencia de resultados L futuros. Para trabajar con secuencias de tareas, hay algunas operaciones comunes. Task.WhenAll y Task.WhenAny son operaciones integradas para los requisitos más comunes. Si desea esperar hasta que todas las asignaciones se hayan completado, puede hacer:

L[] mappedItems = await Task.WhenAll(mappingTasks);

Si prefiere manejar cada elemento a medida que se completa, puede usar OrderByCompletion de mi biblioteca AsyncEx :

Task<L>[] orderedMappingTasks = mappingTasks.OrderByCompletion(); foreach (var task in orderedMappingTasks) { var mappedItem = await task; ... }

Tengo el siguiente código, convirtiendo elementos entre los tipos R y L usando un método asíncrono:

class MyClass<R,L> { public async Task<bool> MyMethodAsync(List<R> remoteItems) { ... List<L> mappedItems = new List<L>(); foreach (var remoteItem in remoteItems ) { mappedItems.Add(await MapToLocalObject(remoteItem)); } //Do stuff with mapped items ... } private async Task<L> MapToLocalObject(R remoteObject); }

¿Es posible escribir usando una llamada IEnumerable.Select (o similar) para reducir las líneas de código? Intenté esto:

class MyClass<R,L> { public async Task<bool> MyMethodAsync(List<R> remoteItems) { ... List<L> mappedItems = remoteItems.Select<R, L>(async r => await MapToLocalObject(r)).ToList<L>(); //Do stuff with mapped items ... } }

Pero me sale un error:

"No se puede convertir la expresión lambda asíncrona al tipo delegado ''System.Func<R,int,L>'' . Una expresión lambda asíncrona puede devolver void , Task o Task<T> , ninguno de los cuales se puede convertir a ''System.Func<R,int,L>'' . "

Creo que me estoy perdiendo algo sobre las palabras clave async / await, pero no puedo averiguar qué. ¿Alguien sabe cómo puedo modificar mi código para que funcione?