Home > front end >  How to return the not-cancelled tasks from Task.WhenAll execution
How to return the not-cancelled tasks from Task.WhenAll execution

Time:10-15

I have a list of tasks that are cancellable; they have their CancellationTokenSource. Their cancellation is independent of others. I want to return all the not-canceled tasks from Task.WhenAll.

var tasks = new List<Task<string>>();

/** some code here **/

var done = await Task.WhenAll(tasks); // This throws an OperationCanceledException,
                                      // when at least one task is cancelled.

There are questions in the StackOverflow "how to cancel a task inside a task," but this question here is not that.

CodePudding user response:

You can retry the rest of the tasks by looping Task.WhenAll

var tasks = new List<Task<string>>();

/** some code here **/
var notCanceled = tasks;
do
{
    try
    {
        await Task.WhenAll(notCanceled);
        break;
    }
    catch (OperationCanceledException)
    {
        notCanceled = notCanceled.Where(t => !t.IsCanceled).ToArray();
    }
} while (notCanceled.Any())

CodePudding user response:

One way to do it is to store the Task.WhenAll task in a Task variable, so that you can add a catch block that handles exclusively the IsCanceled case.

var tasks = new List<Task<string>>();

/** some code here **/

Task whenAll = Task.WhenAll(tasks);
Task<string>[] successfullyCompletedTasks;

try
{
    await whenAll;
    successfullyCompletedTasks = tasks.ToArray();
}
catch when (whenAll.IsCanceled)
{
    successfullyCompletedTasks = tasks.Where(t => !t.IsCanceled).ToArray();
}

// Make sure that our assumptions do not contradict the reality
Debug.Assert(successfullyCompletedTasks.All(t => t.IsCompletedSuccessfully));
  • Related