Search code examples
.net-4.0tasktask-parallel-librarycontinuations

Is it possible to continue with task C after A and B run to completion without fault or cancellation using a single TPL method?


I've tried to use Task.Factory.ContinueWhenAll() a few times now with the intent of invoking a continuation only when all the antecedents run to completion without any errors or cancellations. Doing so causes an ArgumentOutOfRangeException to be thrown with the message,

It is invalid to exclude specific continuation kinds for continuations off of multiple tasks. Parameter name: continuationOptions

For example, the code

var first = Task.Factory.StartNew<MyResult>(
    DoSomething,
    firstInfo,
    tokenSource.Token);
var second = Task.Factory.StartNew<MyResult>(
    DoSomethingElse,
    mystate,
    tokenSource.Token);
var third = Task.Factory.ContinueWhenAll(
    new[] { first, second },
    DoSomethingNowThatFirstAndSecondAreDone,
    tokenSource.Token,
    TaskContinuationOptions.OnlyOnRanToCompletion, // not allowed!
    TaskScheduler.FromCurrentSynchronizationContext());

is not acceptable to the TPL. Is there a way to do something like this using some other TPL method?


Solution

  • There doesn't appear to be a direct way to do this. I've gotten around this by changing OnlyOnRanToCompletion to None and checking to see if Exception is non-null for each task passed into the continuation. Something like

    private void DoSomethingNowThatFirstAndSecondAreDone(Task<MyResult>[] requestTasks)
    {
        if (requestTasks.Any(t => t.Exception != null))
            return;
    
        // otherwise proceed...
    }
    

    works, but this doesn't seem to be a very satisfying way to handle the case with multiple antecedents and breaks with the pattern the single-case Task.Factory.ContinueWith uses.