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));