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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…