c# - tasks - ¿Hay un Task.WaitAll genérico?
task whenall example c# (3)
Estoy bastante seguro de que es una operación segura, incluso con la advertencia, pero si realmente quisieras evitar una mejor opción que crear tu propia implementación sería simplemente convertir tu parámetro de tasks
en el tipo que desea:
Task.WaitAll(tasks.Cast<Task>().ToArray())
Eso mata los garabatos azules para mí, me permite mantener mis tasks
genéricas de forma variable y no me obliga a crear un montón de nuevo código aterrador que en última instancia es innecesario.
Comienzo algunas tareas paralelas, como esta:
var tasks =
Enumerable.Range(1, 500)
.Select(i => Task.Factory.StartNew<int>(ProduceSomeMagicIntValue))
.ToArray();
y luego únete a ellos
Task.WaitAll(tasks);
En esta última línea, aparece un marcador ondulado azul debajo de las tasks
, con un mensaje de advertencia:
Co-variant array conversion from Task[] to Task[] can cause run-time exception on write operation.
Entiendo por qué recibo este mensaje, pero ¿hay alguna forma de evitarlo? (por ejemplo, como una versión genérica de Task.WaitAll()
?)
Puede crear un método de extensión para hacer esto.
No sé la implementación exacta de WaitAll, pero podemos suponer que espera a que se complete cada elemento:
static class TaskExtensions
{
public static void WaitAll<T>(this Task<T>[] tasks)
{
foreach (var item in tasks)
{
item.Wait();
}
}
}
Luego llama, desde tu código actual:
tasks.WaitAll();
Editar
La implementación real es un poco más compleja. He omitido el código de esta respuesta porque es bastante largo.
Puede modificar esto para soportar tareas genéricas.
Un método genérico de Task.WaitAll implicaría que todas las tareas tendrían que devolver el mismo tipo, que sería de utilidad extremadamente limitada. Escribir algo así podría hacerse manualmente (ver la respuesta de Bas Brekelmans), pero esto no permitirá ContinueWith o cancelación sin mucho trabajo.
Una solución simple si no está utilizando la matriz para nada más es
.ToArray<Task>();