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
,Task
oTask<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?