I have the following code:
List<Task<bool>> tasks = tasksQuery.ToList(); while (tasks.Any()) { Task<bool> completedTask = await Task.WhenAny(tasks); if (await completedTask) return true; tasks.Remove(completedTask); }
It launches tasks in parallel. When first completed task returns true, the method returns true.
My questions are:
By using Task. WhenAny, you can start multiple tasks at the same time and process them one by one as they're completed rather than process them in the order in which they're started. The following example uses a query to create a collection of tasks. Each task downloads the contents of a specified website.
As others have noted, Task. WhenAll only aggregates the tasks; it does not start them for you.
Incidentally, I am just reading Concurrency in C# CookBook, by Stephen Cleary, and I can refer to some parts of the book here, I guess.
From Recipe 2.5 - Discussion, we have
When the first task completes, consider whether to cancel the remaining tasks. If the other tasks are not canceled but are also never awaited, then they are abandoned. Abandoned tasks will run to completion, and their results will be ignored. Any exceptions from those abandoned tasks will also be ignored.
Another antipattern for
Task.WhenAny
is handling tasks as they complete. At first it seems like a reasonable approach to keep a list of tasks and remove each task from the list as it completes. The problem with this approach is that it executes in O(N^2) time, when an O(N) algorithm exists.
Besides that, I think WhenAny
is surely the right approach. Just consider the following Leonid approach of passing the same CancellationToken
for all tasks and cancel them after the first one returns. And even that, only if the cost of these operations is actually taxing the system.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With