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 devolvervoid,TaskoTask<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?