Under your provided implementation, the Task.WaitAll
call blocks the calling thread until all tasks have completed. It would only proceed to the next line and perform the Exists
check after this has happened. If you remove the Task.WaitAll
, then the Exists
check would cause the calling thread to block on each task in order; i.e. it first blocks on tasks[0]
; if this returns false, then it would block on tasks[1]
, then tasks[2]
, and so on. This is not desirable since it doesn't allow for your method to finish early if the tasks complete out of order.
If you only need to wait until whichever task returns true first, then you could use Task.WhenAny
. This will make your asynchronous method resume as soon as any task completes. You can then check whether it evaluated to true and return success immediately; otherwise, you keep repeating the process for the remaining collection of tasks until there are none left.
If your code was running as an application (WPF, WinForms, Console), then the remaining tasks would continue running on the thread pool until completion, unless the application is shut down. Thread-pool threads are background threads, so they won't keep the process alive if all foreground threads have terminated (e.g. because all windows were closed).
Since you're running a web app, you incur the risk of having your app pool recycled before the tasks have completed. The unawaited tasks are fire-and-forget and therefore untracked by the runtime. To prevent this from happening, you can register them with the runtime through the HostingEnvironment.QueueBackgroundWorkItem
method, as suggested in the comments.
[HttpPost]
public async Task<IActionResult> PostCall()
{
var tasks = Enumerable
.Range(0, 10)
.Select(Manager.SomeMethodAsync)
.ToList();
foreach (var task in tasks)
HostingEnvironment.QueueBackgroundWorkItem(_ => task);
while (tasks.Any())
{
var readyTask = await Task.WhenAny(tasks);
tasks.Remove(readyTask);
if (await readyTask)
return new ObjectResult("At least one task returned true");
}
return new ObjectResult("No tasks returned true");
}