RobDog888
RobDog888

Reputation: 239

Task Cancelation upon error before all tasks are finished

So Im trying to cancel a task when an error state occurs and throw a taskcancelationsource.cancel(true) which in turn throws an exception.

Problem is that when the error occurs the cancellation doesnt get invoked until after all the tasks have finished. The IsInError.Value is set in a NotifyCollectionChanged event which gets fired when an error message is added to the messages collection.

I have to do the "await Task.WhenAll(tasks)" which is probably keeping everything running until they are all done and I can evaluate if there was an error.

return Task.Run(async () =>
{
    concreteModel.TotalStepCount.Value = 11;
    try
    {
        if (args.EventArgs.EtlOperationType == EtlOperationType.StandardVehicle)
        {
            concreteModel.CompletedStepCount.Value += 1;
        }
        List<Task> tasks = new List<Task>();
        tasks.Add(Task.Run(() => StandardVehicleConversionStorageProxy.ConvertData(container, importRawData), taskCancellationToken));

        await Task.WhenAll(tasks);
        if (concreteModel.IsInError.Value)
        {
             taskCancellationTokenSource.Cancel(true);
        }
    }
    finally
    {
        conversionOperation.IsInProgress.Value = false;
        if (subscription != null)
        {
            subscription.Dispose();
        }
    }
}, taskCancellationToken);

And the task cancellation error is handled in the calling procedure...

private async Task<bool> convertAsync()
{
    try
    {
        await ConversionOperations.Single(x => x.OperationType == EtlOperationType.StandardVehicle).ConvertAsync(Container, _cancellationSource, ImportRawData);
    }
    catch (TaskCanceledException ex)
    {
        // handle the throw task cancellation exception
        ex.Task.Dispose();
        return false;
    }
    finally
    {
        IsConverting.Value = false;
    }
    return true;
}

Upvotes: 0

Views: 228

Answers (1)

Zer0
Zer0

Reputation: 7354

You're checking for an error after calling await Task.WhenAll(tasks);. This won't happen until all tasks are complete.

Instead you should call taskCancellationTokenSource.Cancel(true); in an event handler while the tasks are still running.

You'll also need to pass taskCancellationToken to StandardVehicleConversionStorageProxy.ConvertData and check for token cancellation using CancellationToken.IsCancellationRequested or CancellationToken.ThrowIfCancellationRequested () to handle the cancel request.

Upvotes: 1

Related Questions