Nella mia applicazione sono presenti 3 attività responsabili della ricezione dei dati dai database.
Fino ad ora ho eseguito tutte le attività una dopo l'altra. Se prima avevate finito e avevate Risultato, questi erano i miei dati, se ora avessi iniziato il secondo compito e ho controllato di nuovo.Task.Factory.ContinueWhenQualsiasi operazione continua quando un'operazione termina senza eccezioni
Recentemente ho trovato informazioni che posso avviare più attività e continuare quando una di esse termina con Task.Factory.ContinueWhenAny
. Funziona bene se tutte le mie attività non generano eccezioni, ma se qualche attività fallisce non riesco a ottenere i risultati che voglio.
Ad esempio:
var t1 = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 1;
});
var t2 = Task.Factory.StartNew(() =>
{
Thread.Sleep(2000);
throw new Exception("My error");
return 2;
});
var t3 = Task.Factory.StartNew(() =>
{
Thread.Sleep(4000);
return 3;
});
Task.Factory.ContinueWhenAny(new[] {t1, t2,t3}, (t) =>
{
Console.WriteLine(t.Result);
});
Questo codice inizia 3 compiti e aspetta fino a quando uno di loro finitura. Poiché t2
genera un'eccezione dopo 2 secondi, è disponibile in ContinueWhenAny
.
Dal codice sopra vorrei ottenere 3 in t.Result
.
Esiste un'opzione per continuare solo quando l'attività è stata completata correttamente? Qualcosa di simile Task.Factory.ContinueWhenAnyButSkipFailedTasks
EDIT 1 Questa è la mia soluzione per ora sulla base di @Nitram risposta:
var t1 = Task.Factory.StartNew(() =>
{
var rnd = new Random();
Thread.Sleep(rnd.Next(5,15)*1000);
throw new Exception("My error");
return 1;
});
var t2 = Task.Factory.StartNew(() =>
{
Thread.Sleep(2000);
throw new Exception("My error");
return 2;
});
var t3 = Task.Factory.StartNew(() =>
{
throw new Exception("My error");
return 3;
});
var tasks = new List<Task<int>> { t1, t2, t3 };
Action<Task<int>> handler = null;
handler = t =>
{
if (t.IsFaulted)
{
tasks.Remove(t);
if (tasks.Count == 0)
{
throw new Exception("No data at all!");
}
Task.Factory.ContinueWhenAny(tasks.ToArray(), handler);
}
else
{
Console.WriteLine(t.Result);
}
};
Task.Factory.ContinueWhenAny(tasks.ToArray(), handler);
Che cosa ho bisogno ora è come gettare un'eccezione quando tutte le attività gettano eccezione?
Forse questo può essere modificato in un unico metodo che restituirebbe compito - qualcosa come attività figlio?
Penso che sia necessario scrivere il proprio Task.WhenQualsiasi versione che richiede un Func che specifica se questo particolare completamento attività deve completare l'WhenAny. –
usr