Поток данных TPL, исключение в блоке обработки ошибок не распространяется - PullRequest
0 голосов
/ 20 ноября 2018

Я использую блок потока данных TPL для обработки потока сообщений.Моя сеть потока данных состоит из двух блоков, BufferBlock и ActionBlock, с блоком действия, определяемым как:

        _actionBlock = new ActionBlock<Func<Task>>((Action<Func<Task>>) ProcessRequest,
            new ExecutionDataflowBlockOptions()
            {
                MaxDegreeOfParallelism = 4,
            });

Если в блоке действия возникает ошибка, я хочу, чтобы ошибка распространялась вверхи выйдите из приложения.Позже я планирую добавить здесь логику для обработки временных ошибок, но сейчас любые ошибки должны приводить к выходу приложения с подробными сведениями об ошибках.Для этого я добавил раздел ContinueWith, например:

        _actionBlock
            .Completion
            .ContinueWith(dbt =>
                {
                    var inner = dbt.Exception.InnerExceptions.First();
                    throw inner;
                },
                TaskContinuationOptions.OnlyOnFaulted
            );

Проблема в том, что «throw inner» не распространяется никуда, приложение просто продолжает, как если бы исключение былобыть проглоченнымУ меня больше нет обработчиков исключений в моем коде.В качестве эксперимента я попытался

  • Повторно выдать исключение, используя

       Dispatcher.CurrentDispatcher.Invoke(() => throw ...)
    
  • Проверка того, что содержимое ContinueWith работает в пользовательском интерфейсенить.

  • Обработка любых исключений верхнего уровня с использованием:

    currentDomain.UnhandledException += new UnhandledExceptionEventHandler(ToplevelHandler);
    

(выброшенное исключение никогда не достигает TopLevelHandler)

Ни один изэто помогло.

Как сделать исключение, которое я выбрасываю внутри функции ContinueWith, распространять в верхнюю часть приложения и завершать работу приложения с сообщением об ошибке?

1 Ответ

0 голосов
/ 12 декабря 2018

Цитата из Concurrency в C # Cookbook (Стивен Клири):

Чтобы отловить исключения из блока Dataflow, дождитесь его свойства Completion.Свойство «Завершение» возвращает задание, которое будет выполнено после завершения блока, и в случае сбоя блока также будет выполнена задача «Завершение».

actionBlock = new ActionBlock<Func<Task>>((Action<Func<Task>>) ProcessRequest,
    new ExecutionDataflowBlockOptions()
    {
        MaxDegreeOfParallelism = 4,
    });
await actionBlock.Completion;
...