2012-03-30 3 views
6

Я много читал о том, как обрабатывать исключения в TPL, но на самом деле не понимаю.Исключение обработки в 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 не будет работать.


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

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; 
} 
+0

Я думал о вызове 't.Wait()' в попытке продолжения и игнорирования исключения. Но это не сработает, потому что продолжение может быть выполнено после другого 'Wait()' throws. – svick

ответ

3

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

Но если вы ждете своего task3, все должно работать должным образом.

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

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

(Reference here)

И, наконец, еще один хороший источник на How to handle exceptions thrown by tasks

Я надеюсь, что это помогает.

+1

Думаю, я понял. Wait всегда вызывает исключение, даже если я получаю доступ к свойству .Exception. Однако доступ к .Exception изменяет исключение, чтобы не быть «необработанным», поэтому финализатор задачи не будет бросать. Быстрый тест, похоже, точно подтверждает это. благодаря – adrianm

Смежные вопросы