2015-08-10 8 views
7

Einige von uns bevorzugen es, in einem Ausnahmestil zu codieren. Wenn Sie jedoch auf eine Task Parallel Library-Aufgabe warten und die Task eine Ausnahme ausgelöst hat, wird auch eine Ausnahme für den aufrufenden Thread ausgelöst. Gibt es einen (vorzugsweise Standard) Weg, um dieses Verhalten zu vermeiden und nur die Antwort auf Ausnahmen zu überprüfen, wenn Sie es zurückbekommen?Gibt es eine Möglichkeit, auf eine TPL-Aufgabe zu warten, ohne eine Ausnahme auszulösen?

+0

Also im Grunde fragen Sie, ob einige Code eine Ausnahme warf, gibt es eine Möglichkeit, es zu erkennen, ohne es zu fangen? –

+0

Sind Sie absolut sicher, dass Sie * auf die Aufgabe * warten müssen? Ich würde dir empfehlen '' ContinueWith (...) 'was auch immer du nach dem Wait Call gemacht hast. –

+1

Dies ist eine Instanz, in der Sie Fortsetzungen verwenden sollten, um den Status der Vorgängeraufgabe abzufragen. Die Fortsetzung ist für TPL von grundlegender Bedeutung. Vermeiden Sie Hacking um sie herum. Genauer gesagt ist das Verschlucken von Ausnahmen ein Code-Geruch. – Gusdor

Antwort

7

können Sie Task.WaitAny wie verwenden:

 var task = Task.Run(() => 
     { 
      // ... 
      throw new Exception("Blah"); 
     }); 
     Task.WaitAny(task); 
     if (task.IsFaulted) 
     { 
      var error = task.Exception; 
      // ... 
     } 
     else if (task.IsCanceled) 
     { 
      // ... 
     } 
     else 
     { 
      // Success 
     } 
2

Basierend auf dem, was Sie geschrieben haben, könnte die Ausnahme abfangen und die Überprüfung der IsFaulted Eigenschaft Ihre Lösung sein? IsFaulted

+0

Ich ging mit dem Task.WaitAny Ansatz. Um Ihnen einen Kontext dafür zu geben, warum der Code aufgerufen wurde, war ein Bibliothekscode, den ich nicht ändern konnte und der von außerhalb von TPL aufgerufen wurde, aber Ausnahmen waren ziemlich üblich und obwohl sie gehandhabt werden mussten, gab es eine Menge Lärm damit umzugehen, wenn man auf "Pause bei Ausnahme" klopft, was ich die ganze Zeit mache. –

1

Die Ausnahme in der Task abfangen und im Ergebnis zurückgeben?

var task1 = Task.Factory.StartNew(() => 
{ 
    try 
    { 
     throw new MyCustomException("I'm bad, but not too bad!"); 
    } 
    catch(Exception ex) 
    { 
     return new Result { Error = ex }; 
    } 
}); 
3

Leider ist diese Funktionalität nicht integriert. Verwenden Sie diese Problemumgehung:

Sie können dies zu einer Erweiterungsmethode machen.

+1

Können Sie erklären, warum diese Lösung das Problem anspricht? – Gusdor

+1

@Gusdor was meinst du? es macht genau das, was das OP will. Warten auf eine Aufgabe, ohne eine Ausnahme auszulösen. – boot4life

4

Sie können nicht auf einem fehlerhaften Aufgabe warten, ohne eine Ausnahme zu erhöhen. Aber Sie können zu dieser Aufgabe auf eine Fortsetzung warten, die nur beenden, nachdem die ursprüngliche Aufgabe ohne Auslösen einer Ausnahme beendet:

public static Task SwallowExceptions(this Task task) 
{ 
    return task.ContinueWith(_ => { }); 
} 

faultedTask.SwallowExceptions().Wait(); 
if (faultedTask.IsFaulted) 
{ 
    // handle exception 
} 

Wenn Ihre Aufgabe einen Wert zurückgibt, Sie, dass in der Extension-Methode darstellen und Rückkehr der tatsächliche Wert, wenn es keine Ausnahmen oder den Standardwert gab, wenn es gab:

public static Task<T> SwallowExceptions<T>(this Task<T> task) 
{ 
    return task.ContinueWith(completedTask => 
     completedTask.IsFaulted 
      ? default(T) 
      : completedTask.Result); 
} 
Verwandte Themen