Frage

static async void Main(string[] args)
{
    Task t = new Task(() => { throw new Exception(); });

    try
    {                
        t.Start();
        t.Wait();                
    }
    catch (AggregateException e)
    {
        // When waiting on the task, an AggregateException is thrown.
    }

    try
    {                
        t.Start();
        await t;
    }
    catch (Exception e)
    {
        // When awating on the task, the exception itself is thrown.  
        // in this case a regular Exception.
    }           
}

In TPL ist es bei einer Ausnahme in eine Aufgabe mit einer AggregateException eingewickelt.
Das gleiche passiert jedoch nicht, wenn die Verwendung der verwendet wird erwarten Stichwort.
Was ist die Erklärung für dieses Verhalten?

War es hilfreich?

Lösung

Das Ziel ist es, es aussehen zu lassen/zu handeln wie die synchrone Version. Jon Skeet macht einen großartigen Job und erklärt dies in seiner Eduasync -Serie, insbesondere in diesem Beitrag:

http://codeblog.jonskeet.uk/2011/06/22/eduasync-part-11-more-sophisticated-but-lossy-exception-handling/

Andere Tipps

In tpl AggregateException wird verwendet, weil Sie mehrere Aufgaben im Wartenbetrieb haben können (Aufgaben können untergeordnete Aufgaben angehängt werden), so dass viele von ihnen Ausnahmen werfen können. Ansehen Ausnahmen bei Kinderaufgaben Abschnitt hier:

https://msdn.microsoft.com/ru----RU/Library/dd997417(v=vs.110).aspx

Im await Sie haben immer nur eine Aufgabe.

Siehe auch https://msdn.microsoft.com/ru----RU/Library/dd997415(v=vs.110).aspx

Hier finden Sie eine gute Erklärung im Detail von Stephen Toub, warum es einen Unterschied im Ausnahmeart zwischen Aufgabe gibt.

Aufgabenausnahmehandling in .net 4.5

Beim Entwerfen von Aufgaben. Erwarten Sie in .NET 4, wir haben uns immer für ein Aggregat ausgewählt. Diese Entscheidung wurde von der Notwendigkeit beeinflusst, Details nicht zu überschreiben, sondern auch durch den primären Anwendungsfall für Aufgaben zu diesem Zeitpunkt, die von Gabel/Join -Parallelität, bei der das Potenzial für mehrere Ausnahmen weit verbreitet ist.

Ähnlich wie auf Task.wait auf hohem Niveau (dh vorwärts Fortschritt erst nach Abschluss der Aufgabe), stellt „Warte Task“ einen ganz anderen primären Szenarien dar. Anstatt für die Parallelität für Gabel/Join verwendet zu werden, besteht die häufigste Verwendung von „wartender Aufgabe“ darin, ein sequentielles, synchrone Code zu nehmen und ihn in ein sequentielles, asynchrones Stück Code zu verwandeln. An Stellen in Ihrem Code, an denen Sie einen synchronen Betrieb ausführen, ersetzen Sie sie durch einen asynchronen Betrieb, der durch eine Aufgabe dargestellt wird, und „warten“. Daher können Sie zwar sicherlich auf Fork-/Join -Operationen warten (z. B. die Verwendung von Aufgaben), aber nicht der 80% -Schall. Darüber hinaus sieht .NET 4.5 die Einführung von System.Runtime.Exceptionsservices.ExceptionDispatchInfo, das das Problem löst, dass Sie Ausnahmen über Threads hinweg marschieren können, ohne Ausnahmetails wie Stack Trace und Watson Buckets zu verlieren. Bei einem Ausnahmebobjekt übergeben Sie es an ExceptionDispatchInfo.Create, das ein ExceptionDispatchInfo -Objekt zurückgibt, das einen Verweis auf das Ausnahmebobjekt und eine Kopie der Its -Details enthält. Wenn es Zeit ist, die Ausnahme auszulösen, wird die Wurfmethode von ExceptionDispatchInfo verwendet, um den Inhalt der Ausnahme wiederherzustellen und ohne die ursprünglichen Informationen zu verlieren (die aktuellen Call -Stack -Informationen werden an das angehängt, was bereits in der Ausnahme gespeichert ist).

Angesichts dessen und erneut die Wahl, immer das erste oder immer ein Aggregat zu werfen, um zu „warten“, entscheiden wir uns für immer das erste. Dies bedeutet jedoch nicht, dass Sie keinen Zugriff auf die gleichen Details haben. In allen Fällen gibt die Ausnahmeeigenschaft der Aufgabe weiterhin eine AggregateException zurück, die alle Ausnahmen enthält, sodass Sie bei Bedarf auf Task.Exception zurückgreifen können. Ja, dies führt zu einer Diskrepanz zwischen dem Ausnahmemittel Verhalten beim Wechsel zwischen „task.wait ()“ und „Warte auf die Aufgabe“, aber wir haben das als das bedeutende kleinere von zwei Übeln angesehen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top