Task.Factory.StartNew () не включает исключение при использовании ContinueWith () - PullRequest
0 голосов
/ 14 мая 2019

Я пытаюсь создать параллельный процесс, который бы не блокировал мой основной поток, но все равно регистрировал ошибки в случае исключения.Изначально у меня был такой код:

var task = Task.Run(
    () => _db.addData());

task.ContinueWith(continuationTask =>
    {
        if (continuationTask.Exception != null)
        {
            _logger.LogError(continuationTask.Exception, "Failed to log mismatch");
        }
    },
    _taskScheduler);

При запуске приложения код _taskScheduler устанавливается на TaskScheduler.Current.При выполнении этого он корректно выполняет код параллельно, и когда возникает проблема с базой данных, continuationTask.Exception содержит соответствующее сообщение об исключении.

Весь смысл указания TaskScheduler был таким, чтобы я мог контролироватьпорядок выполнения в модульном тесте.В настоящий момент в модульном тесте исходное задание и продолжение будут выполняться с использованием разных планировщиков заданий - TaskScheduler и MockTaskScheduler соответственно.(для краткости не показан код модульного теста, но MockTaskScheduler - это просто пользовательская реализация, которая позволяет мне ставить в очередь и выполнять задачи)

Поскольку Task.Run не принимает TaskScheduler в качестве параметра, который я пыталсяизменение кода на

var task = Task.Factory.StartNew(
    () => _db.addData(),
    CancellationToken.None,
    TaskCreationOptions.None,
    _taskScheduler);

task.ContinueWith(continuationTask =>
    {
        if (continuationTask .Exception != null)
        {
            _logger.LogError(continuationTask.Exception, "Failed to log mismatch");
        }
    },
    _taskScheduler);

Это делает мой тест безупречным, поскольку теперь я могу контролировать выполнение каждой задачи, поскольку они используют одну и ту же инъекцию _taskScheduler.Однако при запуске кода приложения с использованием TaskScheduler.Current, continuationTask.Exception всегда равен нулю, что не позволяет мне регистрировать любые исключения.

Есть ли причина, по которой Task.Run заполняет continuationTask.Exception и Task.Factory.StartNew не«т?Я что-то упустил?

1 Ответ

1 голос
/ 17 мая 2019

Как отметил @Mike Zboray в комментариях, мне нужно было позвонить task.Unwrap().ContinueWith(), так как у меня были вложенные задачи.Это необходимо только при использовании Task.Factory.StartNew(), поскольку Task.Run() автоматически разворачивает вложенные задачи.

Мой окончательный код выглядит следующим образом:

var task = Task.Factory.StartNew(
    () => _db.addData(),
    CancellationToken.None,
    TaskCreationOptions.None,
    _taskScheduler);

task.Unwrap().ContinueWith(continuationTask =>
    {
        if (continuationTask .Exception != null)
        {
            _logger.LogError(continuationTask.Exception, "Failed to log mismatch");
        }
    },
    _taskScheduler);
...