2014-07-21 14 views
7

ich zu C# bin hier und ich finde Ausnahmen ein wenig verwirrend ... Ich habe einen Web-App mit dem folgenden Code:Timeout, TaskCanceledException C#

try 
{ 
    //do something 
} 
catch (TimeoutException t) 
{ 
    Console.WriteLine(t); 
} 
catch (TaskCanceledException tc) 
{ 
    Console.WriteLine(tc); 
} 
catch (Exception e) 
{ 
    Console.WriteLine(e); 
} 

Wenn ich den Code debuggen, es die E wirft Exception, die allgemeinste und wenn ich über die Ausnahme Info schweben, stellt sich heraus, dass es die TaskCanceledException ist. Warum wird die TaskCanceledException nicht abgefangen? Wenn die Ausnahme ein TimeoutException wäre würde es die TimeoutException fangen oder würde es auch die Exception fangen? Warum das?

+3

Sind Sie sicher, dass es kein 'AggregationException' von einem' Task' Objekt geworfen? Zeigen Sie uns den werfenden Anruf –

+0

... ja, es ist die System.AggregateException und die InnerException ist die System.Threading.Task.TaskCanceledException. – Marta

Antwort

6

Wenn Sie eine Exception fangen, müssen Sie sicherstellen, dass es genau die Ausnahme wird geworfen. Wenn Sie Task.Run oder Task.Factory.Startnew verwenden und normalerweise eine Ausnahme von einer Task ausgelöst wird (sofern die Aufgabe nicht mit dem Schlüsselwort await abgewartet wird), handelt es sich bei der äußeren Ausnahme um eine AggregateException, da eine Task Einheit untergeordnete Aufgaben haben kann Werfen Sie auch Ausnahmen.

Von Exception Handling (Task Parallel Library):

Unbehandelte Ausnahmen, die durch Benutzercode geworfen werden, die innerhalb einer Task ausgeführt werden zurück an den Verbindungsfaden propagieren, außer in bestimmten Szenarien, die später in diesem Thema beschrieben werden. Ausnahmen werden weitergegeben, wenn Sie eine der statischen Task Task.Wait oder Task.Wait Methoden verwenden, und Sie behandeln sie, indem Sie den Aufruf in einer try-catch-Anweisung einschließen. Wenn eine Aufgabe das übergeordnete untergeordnete Aufgaben ist oder wenn Sie auf mehrere Aufgaben warten, können mehrere Ausnahmen ausgelöst werden. Um alle Ausnahmen zurück an den aufrufenden Thread in zu propagieren, umschließt die Task-Infrastruktur sie in einer 0 AggregatException-Instanz . Die AggregateException verfügt über eine InnerExceptions-Eigenschaft, die aufgelistet werden kann, um alle ursprünglichen Ausnahmebedingungen zu untersuchen, die jeweils ausgelöst wurden, und die jeweils einzeln behandeln (oder nicht behandeln). Auch wenn nur eine Ausnahme ausgelöst wird, ist es immer noch in eine AggregateException eingewickelt.

Also, um damit zu umgehen, müssen Sie AggregateException fangen:

try 
{ 
    //do something 
} 
catch (TimeoutException t) 
{ 
    Console.WriteLine(t); 
} 
catch (TaskCanceledException tc) 
{ 
    Console.WriteLine(tc); 
} 
catch (AggregateException ae) 
{ 
    // This may contain multiple exceptions, which you can iterate with a foreach 
    foreach (var exception in ae.InnerExceptions) 
    { 
     Console.WriteLine(exception.Message); 
    } 
} 
catch (Exception e) 
{ 
    Console.WriteLine(e); 
} 
+0

Ok. Jetzt sollte meine App Zeitüberschreitung haben, aber anstelle einer TimeoutException bekomme ich diese AggregateException mit TaskCanceledException innerhalb. Wie bekomme ich das Programm zum Abfangen der TimeoutException? – Marta

+0

ist es grundsätzlich möglich, dass eine TimeoutException anstelle von TaskCanceledException ausgelöst wird? – Marta

+0

Nein, das ist nicht möglich. Eine "AggregateException" wird von einer "Task" ausgelöst, da sie möglicherweise auch untergeordnete Aufgaben enthält. Es ist einfach ein Wrapper. –