1
votes

I am using Task.WhenAll to schedule tasks concurrently (more or less of course) and want to rethrow all exceptions rather than the first one what Task.WhenAll would do. So I want to perfor a continuation whenever any child task faulted or has been canceled. That's what NotOnRanToCompletion means, right?

Well this actually works but in case that all Tasks actually have completed, I get a Task Cancelled exception on the Continuation?

var semaphore = new SemaphoreSlim(10);
var tasks = portList.Select(async port =>
{
    try
    {
        await semaphore.WaitAsync();
        await this.AddDeviceAsync(bioprocessDevicesDto, template, port);
    }
    finally
    {
        semaphore.Release();
    }
});
await Task.WhenAll(tasks).ContinueWith(t =>
{
    // this will make all inner exceptions available
    // never null
    throw t.Exception;
}, TaskContinuationOptions.NotOnRanToCompletion).ConfigureAwait(false);

Visual Studio screenshot

2
Please, do not post code as images - Pavel Anikhouski
From the documentation: "If the criteria specified through the continuationOptions parameter are not met, the continuation task will be canceled instead of scheduled." - Damien_The_Unbeliever
oh boy really? I did not find that. I must have been asleep. Well that pretty much explains it. I actually did not expect this kind of behaviour but well what can I say - yBother
@Damien_The_Unbeliever seems you have an answer here - Pac0
In this case I will use TaskContinuationOptions.None and rethow Exception if !=null. Is checking for Task.Status!=RanToCompletion necessary here? - yBother

2 Answers

2
votes

That behavior is by-design and documented.

Note that your code is not awaiting the task returned from WhenAll; it's awaiting the continuation from ContinueWith.

ContinueWith is a low-level method with dangerous default behavior. Use await instead:

var tasks = portList.Select(...);
var allTask = Task.WhenAll(tasks);
try { await allTask; }
catch { throw allTask.Exception; }
1
votes

When you look at the TaskContinuationOptions for NotOnRanToCompletion, it states:

This option is not valid for multi-task continuations.

I would try changing NotOnRanToCompletion to another option that handles multi-task continuations.