Aufgabe nicht Müll gesammelt

9

Im folgenden Programm würde ich erwarten, dass die Aufgabe gecodiert wird, aber nicht. Ich habe einen Speicher-Profiler verwendet, der gezeigt hat, dass der CancellationTokenSource einen Verweis darauf enthält, obwohl die Aufgabe eindeutig in einem Endzustand ist. Wenn ich TaskContinuationOptions.OnlyOnRanToCompletion entferne, funktioniert alles wie erwartet.

Warum passiert es und was kann ich tun, um es zu verhindern?

%Vor%

Mein Verdacht ist, dass, weil die Fortsetzung niemals ausgeführt wird (sie erfüllt nicht die in ihren Optionen angegebenen Kriterien), sie sich nie vom Kündigungs-Token abmeldet. Der CTS enthält also einen Verweis auf die Fortsetzung, die einen Verweis auf die erste Aufgabe enthält.

Aktualisieren

Das PFX-Team hat bestätigt, dass dies ein Leck zu sein scheint. Um dieses Problem zu umgehen, verwenden wir keine Fortsetzungsbedingungen mehr, wenn Stornierungs-Token verwendet werden. Stattdessen führen wir immer die Fortsetzung aus, überprüfen die Bedingung innerhalb und werfen ein OperationCanceledException , wenn es nicht erfüllt ist. Dies bewahrt die Semantik der Fortsetzung. Die folgende Erweiterungsmethode fasst dies zusammen:

%Vor%     
Eli Arbel 10.10.2013, 14:46
quelle

2 Antworten

5

Kurze Antwort: Ich glaube, das ist ein Speicherleck (oder zwei, siehe unten), und Sie sollten es melden .

Lange Antwort:

Der Grund, warum das Task nicht GCed ist, liegt darin, dass es vom CTS wie folgt erreichbar ist: ctsconttask . Ich denke, dass beide Referenzen in Ihrem Fall nicht existieren sollten.

Die ctscont Referenz ist da, weil cont sich korrekt für die Löschung unter Verwendung des Tokens registriert, aber die Registrierung wird nie aufgehoben. Es wird die Registrierung aufgehoben, wenn Task normal abgeschlossen wird, aber nicht, wenn es abgebrochen wird. Meine Vermutung ist die falsche Logik ist, dass, wenn die Aufgabe abgebrochen wurde, es nicht notwendig ist, die Registrierung von der Stornierung, weil es sein musste, dass die Stornierung, dass die Aufgabe abgebrochen wurde verursacht.

Der Verweis conttask ist da, weil cont tatsächlich ContinuationTaskFromResultTask ist (eine Klasse, die von Task abgeleitet ist). Diese Klasse verfügt über ein Feld, das die Antezedens-Aufgabe enthält, die beendet wird, wenn die Fortsetzung erfolgreich ausgeführt wird, aber nicht, wenn sie abgebrochen wird.

    
svick 11.10.2013, 16:37
quelle
-1

als Zusatz ... In diesem Fall wird der Finalizer aufgerufen:

%Vor%     
Vladimir Gondarev 11.10.2013 07:06
quelle