Home > OS >  Tasks are getting cancelled, but it's not clear why and how
Tasks are getting cancelled, but it's not clear why and how

Time:05-07

I'm working on a large monolith web application running on ASP.NET framework and added a feature. I've build some abstraction in order to run several tasks in parallel.

public interface IImporter
{
    Action[] GetProcessActions();
}

public class ImportTaskFactory : IDisposable
{
    private readonly Task[] _tasks;

    /// <summary>
    /// Immediately starts all the Process tasks
    /// </summary>
    public ImportTaskFactory(CancellationToken cancellationToken, Action<Task> onTaskFaultedAction, IEnumerable<IImporter> importers)
    {
        _tasks = importers
            .SelectMany(importer =>
                importer
                    .GetProcessActions()
                    .Select(action =>
                        Task.Factory.StartNew(action, cancellationToken)
                                    .ContinueWith(onTaskFaultedAction, TaskContinuationOptions.OnlyOnFaulted)))
            .ToArray();
    }

    public void WaitAll(CancellationToken cancellationToken)
    {
        Task.WaitAll(_tasks, cancellationToken);
    }

    public void Dispose()
    {
        foreach (var task in _tasks)
        {
            task?.Dispose();
        }
    }
}

and it's called like

//...
var importers = new IImporter[]
{
   //...three classes deriving from IImporter
}
using (var importTasks =
    new ImportTaskFactory(_cancellationTokenSource.Token, OnTaskFaulted, importers))
    {
        importTasks.WaitAll(_cancellationTokenSource.Token);
    }
//... where:
    private void OnTaskFaulted(Task task)
    {
        Log.Logline(task.Exception.ToString());
        _cancellationTokenSource.Cancel();
    }
//...

However, when running the tasks start out fine and do their work, but seem to stop for unclear reason, each throwing an System.Threading.Tasks.TaskCanceledException (no inner exception). If I look at the passed CancellationToken, cancellation was not requested.

enter image description here

I've been trying to debug this for a couple of hours, but have no idea what's happening. How can the tasks get cancelled this way? How can I debug this? I mean how can I see what triggers the cancellation?

I've set breakpoints in the OnTaskFaulted method, but it never seems to be called... That's the only point where _cancellationTokenSource.Cancel(); is called.

CodePudding user response:

This not an answer to your question. It just shows how to do what you want, without getting these pesky cancellation exceptions:

void ImportTaskFactory(CancellationToken cancellationToken,
    Action<Task> onTaskFaultedAction, IEnumerable<IImporter> importers)
{
    _tasks = importers
        .SelectMany(importer => importer
            .GetProcessActions()
            .Select(action => Task.Run(() =>
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    onTaskFaultedAction(Task.FromException(ex));
                }
            }, cancellationToken))).ToArray();
}

I replaced the Task.Factory.StartNew with Task.Run, because the former requires to pass explicitly the scheduler every time you use it.

Probably it would be simpler if the onTaskFaultedAction parameter was of type Action<Exception> instead of Action<Task>.

  • Related