2 votes

Consommer le résultat d'appels asynchrones (avec un type de retour différent) dès que l'un d'entre eux est terminé ?

Le code suivant démarre T1Async() , T2Async() , T3Async() , T4Async() et attendre qu'ils soient tous terminés avant de consommer les résultats de ces appels. Cependant, le temps d'exécution de ces appels asynchrones peut être court ou très long de manière aléatoire.

Task<int> T1Async() { };
Task<string> T2Async() { };
Task<ClassX> T3Async() { };
Task<ClassY> T4Async() { };

var t1 = T1Async();
var t2 = T2Async();
var t3 = T3Async();
var t4 = T4Async();

var v1 = await t1;
var v2 = await t2;
var v3 = await t3;
var v4 = await t4;
// Or Task.WhenAll(new Task[] { t1, t2, t3, t4 });

UseV1(v1); // Want these calls be run asap
UseV2(v2);
UseV3(v3);
UseV4(v4);

UseAll(v1, v2, v3, v4); // Need all the result here

Comment consommer les résultats dès que l'appel est effectué et s'assurer que tous les résultats sont consommés ?

3voto

Wouter Huysentruit Points 8965

Vous voulez donc exécuter le UseVX en parallèle, mais attend tous les résultats (de type différent) pour les transmettre à la tâche UseAll méthode.

Utilisation Task.Run

var t1 = Task.Run(async () => { var x = await T1(); UseV1(x); return x; });
var t2 = Task.Run(async () => { var x = await T2(); UseV2(x); return x; });
var t3 = Task.Run(async () => { var x = await T3(); UseV3(x); return x; });
var t4 = Task.Run(async () => { var x = await T4(); UseV4(x); return x; });
await Task.WhenAll(t1, t2, t3, t4);
UseAll(t1.Result, t2.Result, t3.Result, t4.Result);

Utilisation ContinueWith

var t1 = T1().ContinueWith(x => { UseV1(x.Result); return x.Result; });
var t2 = T2().ContinueWith(x => { UseV2(x.Result); return x.Result; });
var t3 = T3().ContinueWith(x => { UseV3(x.Result); return x.Result; });
var t4 = T4().ContinueWith(x => { UseV4(x.Result); return x.Result; });
await Task.WhenAll(t1, t2, t3, t4);
UseAll(t1.Result, t2.Result, t3.Result, t4.Result);

2voto

Stephen Cleary Points 91731

Pour exécuter du code asynchrone simultanément, utilisez l'option Task.WhenAll . Pour exécuter une méthode au fur et à mesure que chaque opération se termine, introduire un nouveau async méthode :

async Task<int> T1AndUseV1Async() { var v1 = await T1Async(); UseV1(v1); return v1; };
async Task<string> T2AndUseV2Async() { var v2 = await T2Async(); UseV2(v2); return v2; };
async Task<ClassX> T3AndUseV3Async() { var v3 = await T3Async(); UseV3(v3); return v3; };
async Task<ClassY> T4AndUseV4Async() { var v4 = await T4Async(); UseV4(v4); return v4; };

var t1 = T1AndUseV1Async();
var t2 = T2AndUseV2Async();
var t3 = T3AndUseV3Async();
var t4 = T4AndUseV4Async();

await Task.WhenAll(t1, t2, t3, t4);

UseAll(await t1, await t2, await t3, await t4);

0voto

dc7a9163d9 Points 2816

Un cas testable :

async Task<int> T1() { return await Task.FromResult(1); }
async Task<string> T2() { return await Task.FromResult("T2"); }
async Task<char> T3() { await Task.Delay(2000); return await Task.FromResult('A'); }
async Task<string> T4() { return await Task.FromResult("T4"); }

var t1 = T1().ContinueWith(x => { Console.WriteLine($"Use T1: {x.Result}"); return x.Result; });
var t2 = T2().ContinueWith(x => { Console.WriteLine($"Use T2: {x.Result}"); return x.Result; });
var t3 = T3().ContinueWith(x => { Console.WriteLine($"Use T3: {x.Result}"); return x.Result; });
var t4 = T4().ContinueWith(x => { Console.WriteLine($"Use T4: {x.Result}"); return x.Result; });
await Task.WhenAll(t1, t2, t3, t4);
Console.WriteLine("Done");

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X