2012-03-30 15 views
6

Ich habe viel gelesen, wie mit Ausnahmen in TPL umzugehen, aber nicht wirklich verstehen.handling exception in Tpl

Hier können Sie dieses Beispiel-Code nehmen:

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); 
} 

ich diese

Catch 1 
Continuation 

Aber ich

Catch 1 
Continuation 
Wait Exception 

wenn Dies bedeutet, dass die Ausnahme als nicht behandelte noch erhalten drucken erwartet die Aufgabe wird abgeschlossen, und der Aufgabenfinalisierer wird die Anwendung schließlich abreißen.

Wie gehe ich mit der Ausnahme in der Fortsetzung um, damit der Finalizer nicht geworfen wird? Gleichzeitig möchte ich, dass die Aufgabe im fehlerhaften Zustand bleibt, so dass die Aufgabe in try/catch nicht funktioniert.


Der Hintergrund ist, dass ich von der Asynchron-Ereignismuster implementieren möchten als here angegeben, aber mit Fehlerbehandlung. Meine vollständige Code sieht wie folgt aus

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

Ich dachte darüber nach, 't.Wait()' in einem Versuch in der Fortsetzung zu nennen und die Ausnahme zu ignorieren. Aber das wird nicht funktionieren, weil die Fortsetzung ausgeführt werden kann, nachdem das andere 'Wait()' wirft. – svick

Antwort

3

Sie tun, um Ihre Wartezeit auf die Aufgabe, die fehlschlägt, und wenn Sie die documentation on Task.Wait sorgfältig lesen, werden Sie, dass Warte sehen die Ausnahme in diesem Fall erneut auslösen.

Aber wenn Sie auf Ihre task3 warten, sollte alles wie erwartet funktionieren.

Natürlich sollten Sie dies im Auge behalten:

Wenn Sie die OnlyOnFaulted Option verwenden, ist garantiert, dass die Exception-Eigenschaft in den vorgängigen nicht null ist. Sie können diese -Eigenschaft verwenden, um die Ausnahme abzufangen und zu sehen, welche Ausnahme die -Aufgabe verursacht hat. Wenn Sie nicht auf die Exception-Eigenschaft zugreifen, wird die Ausnahme nicht behandelt. Wenn Sie versuchen, auf die Eigenschaft Result einer Aufgabe zuzugreifen, die abgebrochen wurde oder einen Fehler aufweist, wird eine neue Ausnahme ausgelöst.

(Referenz here)

Und schließlich noch eine weitere gute Quelle auf How to handle exceptions thrown by tasks

Ich hoffe, das hilft.

+1

Ich denke, ich verstehe es. Wait wird immer eine Ausnahme verursachen, selbst wenn ich auf die .Exception-Eigenschaft zugreife. Durch den Zugriff auf .Exception wird die Ausnahme jedoch so geändert, dass sie nicht "unbehandelt" ist, sodass der Task Finalizer nicht ausgelöst wird. Ein kurzer Test scheint genau das zu bestätigen. Vielen Dank – adrianm