Frage

Ich versuche, die Bedingungen zu erstellen, die diese Ausnahme verursacht:

System.AggregateException: A Task's exception(s) were not observed 
either by Waiting on the Task or accessing its Exception property. 
As a result, the unobserved exception was rethrown by the finalizer thread.`

Ich schrieb dieses Programm denke ich die Ausnahme verursachen würde, aber es funktioniert nicht:

using System;
using System.Threading.Tasks;
namespace SomeAsyncStuff
{
    class Program
    {
        static void Main(string[] args)
        {
            Task.Factory.StartNew(() => { throw new NullReferenceException("ex"); });
            GC.Collect();
            Console.WriteLine("completed");            
        }
    }
}

In meinem realen Anwendung, verwende ich TPL und ich habe nicht meine Ausnahme richtigen Umgang codieren. Als Ergebnis erhalte ich diese Ausnahme. Ich versuche, die gleichen Bedingungen in einem separaten Programm neu erstellen nun mit unbeobachtet Ausnahmen zu experimentieren.

War es hilfreich?

Lösung 5

Ich bin der OP. Getestet habe ich die GC.WaitForPendingFinalizers (), aber es half nicht die Ausnahme neu zu erstellen. Das Problem war, dass die GC.Collect () ausgeführt wurde, bevor die Task gestartet.

Dies ist der richtige Code die Ausnahme zu erstellen:

using System;
using System.Threading;
using System.Threading.Tasks;
namespace SomeAsyncStuff
{
    class Program
    {
        static void Main(string[] args)
        {
            Task.Factory.StartNew(() => { throw new NullReferenceException("ex"); });

            // give some time to the task to complete
            Thread.Sleep(3000);

            GC.Collect();
            // GC.WaitForPendingFinalizers();
            Console.WriteLine("completed"); 
        }
    }
}

Andere Tipps

Sie müssen einen Aufruf an GC.WaitForPendingFinalizers () nach GC.Collect () hinzuzufügen, da Finalizers auf ihrem eigenen Thread ausgeführt werden.

Die Ausnahme wird von TaskExceptionHolder Finalizer geworfen, so dass die Finalizerthread laufen muss, bevor diese Ausnahme ausgelöst. Als Josh weist darauf hin, können Sie, dass durch den Aufruf CG.WaitForPedingFinalizers() passieren warten.

Bitte beachten Sie, dass dieses Verhalten in der aktuellen Async CTP geändert wurde. Ich sprach mit Stephen Toub des PFX Team darüber auf der TechEd Europe in diesem Jahr, und er erklärt, dass sie es für die neue asynchrone Funktionalität zur Arbeit korrekt zu ändern hatte. So, während es noch zu früh, etwas über die nächste Version des Frameworks zu sagen, könnte dieses Verhalten sehr gut in der kommenden Version geändert werden.

@Sly, obwohl man mit einem Arbeits Antwort kam, ich glaube, die meisten Leute würden besser durch beachtend die Fehlermeldung Vorschlag bedient werden „... Warten auf die Aufgabe ...“. Einsteigen GC-Aktivität beteiligt ist ein Zeichen dafür, dass entweder Sie wissen GC eng und haben einen Leistungsengpass oder Sie vermissen den Punkt. In meinem Fall bedeutet es das letztere;) Der StartNew Aufruf einer Aufgabe zurückkehrt so, warum es nicht benutzen? z.

Task myTask = Task.Factory.StartNew (() => { throw new Nullreferenceexception ( "ex"); }); // einige Zeit, um die Aufgabe abzuschließen
geben myTask.Wait ();

Ich bin wirklich überrascht, dass Sie nicht nach Erledigung der Aufgabe richtig Aufruf Code versucht haben, denn wer ist zu sagen, dass jeder Prozess unter 3 Sekunden abgeschlossen wird? Nicht nur das, sondern dass bindet andere Prozesse für volle 3 Sekunden. Ich würde, dass die Umsetzung der Methode ContinueWith () Aufgabe ersetzen Sie die GC nach dem Ausführen des Tasks zu nennen.

Task.Factory
    .StartNew(() => { throw new NullReferenceException("ex"); })
    .ContinueWith(p => GC.Collect());

Wenn Sie blockieren müssen, bis es fertig ist (für die Beispiel-Code Sie debuggen bewertet wurden), können Sie auch eine WaitOne tun, nachdem die Aufgabe beginnen und haben ContinueWith () signalisieren die Warte Handler. Wenn Sie mit dieser dann vielleicht in der Produktion Code tun, was Sie versuchen tatsächlich synchron zu tun ist, wo man sich keine Sorgen machen brauchen über eine Aufgabe überhaupt verwendet wird.

Der einfachste Weg, um den Fehler zu erstellen ist für die Aufgabe vollständig zu warten.

Task task = Task.Factory.StartNew(() => { throw new NullReferenceException("ex"); });
//this is where the exception will be thrown
task.Wait();

Warte Aufruf wird der Anruf blockiert, bis die Aufgabe beendet Ausführung hat.

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