2017-10-10 52 views
5

I mają następujące wymagania: Wariant/C# asynchroniczny/oczekiwać - wiele zadań z korzystną

że ma dwa zadania, zadanie A i zadanie B, które zwracają taki sam typ danych. Jeśli zadanie A, po zakończeniu, ma dane w wyniku, muszę zwrócić wynik zadania A - w przeciwnym razie zwrócę wynik zadania B.

Próbuję zoptymalizować to pod kątem paralelizmu, a ja " nie jestem pewien, czy jest lepszy sposób niż to, co robię. Wydaje się, że jest dużo kodu, aby zrobić to, co chcę.

var firstSuccessfulTask = await Task.WhenAny(taskA, taskB); 
if (firstSuccessfulTask != taskA) 
{ 
    await taskA; 
} 

if (taskA.Result != null) 
{ 
    return taskA.Result; 
} 

return await taskB; 
+3

Najpierw po prostu wywołaj 'await taskA' najpierw i pomiń wywołanie' Task.WhenAny'? – EJoshuaS

Odpowiedz

12

Wystarczy napisać kod dokładnie tak, jak czytają twoje wymagania. zwracaj wynik A, chyba że jest zerowy, w takim przypadku zwróć wynik B.

return await taskA ?? await taskB; 
+3

Czy to nie powinno rozpocząć wykonywanie zadania B do czasu zakończenia zadaniaA, co sprawi, że będą one szeregowe, a nie równoległe? –

+2

@PaulGelardi Jeśli 'taskB' jest tak naprawdę właściwością, która uruchamia zadanie po wywołaniu tego wyrażenia, to tak. Jeśli jest to lokalny/pole, które ma już uruchomione zadanie, to nie. Biorąc pod uwagę konwencję nazewnictwa i fakt, że wielokrotnie używasz 'taskA' (a tym samym wyraźnie nie tworzysz nowych zadań za każdym razem, gdy go używasz, ponieważ gdyby kod był w ogóle nie działa), to jest całkiem jasne, że obie są zmiennymi, a nie wyrażeń, które obliczają nowe zadania. Jeśli naprawdę są wyrażeniami, które obliczają nowe zadania, najpierw musisz zapisać je w zmiennej lokalnej, a następnie wykonaj to. – Servy

+0

To ma sens. Nie wiedziałem, że zadanie B zaczęło się wykonywać, jak tylko nazwałem metodę asynchroniczną - myślałem, że nie zaczęło się, dopóki coś nie czekało, lub na to czekające. –