обработка исключений в Tpl - PullRequest
6 голосов
/ 30 марта 2012

Я много читал о том, как обрабатывать исключения в TPL, но на самом деле не понимаю.

Давайте рассмотрим пример кода:

var task1 = new Task(() => { throw new Exception("Throw 1"); });
var task2 = task1.ContinueWith(t => Console.WriteLine("Catch 1:{0}", t.Exception.Message), 
                              TaskContinuationOptions.OnlyOnFaulted);
var task3 = task2.ContinueWith(t => Console.WriteLine("Continuation"));

task1.Start();
try {
    task1.Wait();
}
catch (Exception ex) {
    Console.WriteLine("Wait Exception: {0}", ex.Message);
}

Я ожидал, что это напечатает

Catch 1
Continuation

Но я получаю

Catch 1
Continuation
Wait Exception

Это означает, что исключение все еще считается необработанным, когда задача завершается, и финализатор задачи в конечном итоге завершит работу приложения.

Как мне обработать исключение внутри продолжения, чтобы финализатор не выдавал? В то же время я хочу, чтобы задача осталась в состоянии сбоя, поэтому перенос задачи в try / catch не будет работать.


В фоновом режиме я хочу реализовать шаблон асинхронных событий, как указано здесь , но с обработкой ошибок.Мой полный код выглядит так

public IAsyncResult Begin(AsyncCallback callback, object state, Action action) {
    var task1 = new Task(action);
    var task2 = task1.ContinueWith(t => HandleException(t.Exception), 
                                   TaskContinuationOptions.OnlyOnFaulted);
    if (callback != null) {
        var task3 = task2.ContinueWith(t => callback(t),
                                      TaskScheduler.FromCurrentSynchronizationContext());
        var task4 = task3.ContinueWith(t => HandleException(t.Exception), 
                                       TaskContinuationOptions.OnlyOnFaulted);
    }

    task1.Start();

    return task;
}

1 Ответ

3 голосов
/ 31 марта 2012

Вы дожидаетесь выполнения задачи, которая не выполнена, и если вы внимательно прочитаете документацию для Task.Wait , вы увидите, что ожидание перезапустит исключение в этом случае.

если вы ждете на task3 все должно работать как положено.

Конечно, вы должны помнить об этом:

Когда вы используете опцию OnlyOnFapted, это гарантирует, чтоСвойство исключения в антецеденте не равно нулю.Вы можете использовать это свойство, чтобы перехватить исключение и посмотреть, какое исключение вызвало ошибку задачи.Если вы не получите доступ к свойству Exception, исключение останется необработанным.Кроме того, если вы попытаетесь получить доступ к свойству Result задачи, которая была отменена или возникла ошибка, будет сгенерировано новое исключение.

(ссылка здесь )

И, наконец, еще один хороший источник о Как обрабатывать исключения, создаваемые задачами

Надеюсь, это поможет.

...