Wie vermeiden Sie Lecks beim Aufruf in der Benutzeroberfläche von System.Threading.Timer?

8

Es scheint so, als würde Invoke auf einem winforms-Steuerelement in einem Callback von einem System.Threading.Timer-Lecks-Handles aufrufen, bis der Zeitgeber entfernt wird. Hat jemand eine Idee, wie man das umgehen kann? Ich muss jede Sekunde einen Wert abfragen und die Benutzeroberfläche entsprechend aktualisieren.

Ich habe es in einem Testprojekt versucht, um sicherzustellen, dass dies tatsächlich die Ursache für das Leck war, das einfach das Folgende ist:

%Vor%

Dies wird 2 Griffe / Sekunde verlieren, wenn Sie im Windows Task-Manager sehen.

    
Davy8 21.10.2009, 19:39
quelle

4 Antworten

6

Invoke verhält sich wie ein BeginInvoke / EndInvoke-Paar, indem es die Nachricht an den UI-Thread sendet, ein Handle erstellt und auf dieses Handle wartet, um festzustellen, wann die Methode Invoked abgeschlossen ist. Es ist dieser Griff, der "leckt". Sie können sehen, dass dies unbenannte Ereignisse sind, die Process Explorer verwenden, um die Handles zu überwachen, während die Anwendung ausgeführt wird .

Wenn IASyncResult IDisposable war, würde die Entsorgung des Objekts dafür sorgen, dass das Handle bereinigt wird. Da dies nicht der Fall ist, werden die Handles bereinigt, wenn der Garbage Collector ausgeführt wird, und ruft den Finalizer des IASyncResult-Objekts auf. Sie können dies sehen, indem Sie GC.Collect () nach jeweils 20 Aufrufen von DoStuff hinzufügen - die Anzahl der Handle wird alle 20 Sekunden verringert. Natürlich ist das "Lösen" des Problems durch Hinzufügen von Aufrufen zu GC.Collect () der falsche Weg, das Problem zu lösen; Lassen Sie den Müllsammler seinen eigenen Job machen.

Wenn Sie den Aufruf aufrufen nicht als synchron verwenden möchten, verwenden Sie BeginInvoke anstelle von Invoke und rufen Sie EndInvoke nicht auf; Das Endergebnis wird dasselbe tun, aber keine Handles werden erstellt oder "durchgesickert".

    
DocMax 21.10.2009, 20:40
quelle
2

Gibt es einen Grund, warum Sie hier keinen System.Windows.Forms.Timer verwenden können? Wenn der Timer an dieses Formular gebunden ist, müssen Sie nicht einmal aufrufen.

    
Joshua 21.10.2009 19:48
quelle
2

Okay, ich habe es ein wenig mehr Zeit gegeben und es sieht so aus, als ob es tatsächlich keine Lecks gibt, es ist nur die unbestimmte Natur des Müllsammlers. Ich schubste es bis 10ms pro Tick hoch und es würde sehr schnell hochklettern und 30 Sekunden später würde wieder fallen.

Um die Theorie zu bestätigen, habe ich GC.Collect () bei jedem Callback manuell aufgerufen (tu dies nicht in realen Projekten, das war nur zum Testen, es gibt zahlreiche Artikel darüber, warum es eine schlechte Idee ist) und die Handle-Anzahl war stabil.

    
Davy8 21.10.2009 20:44
quelle
0

Interessant - Dies ist keine Antwort, aber basierend auf Andrejs Kommentar hätte ich gedacht, dass dies nicht auf die gleiche Art und Weise Leak Handles mit der gleichen Geschwindigkeit wie das OP erwähnt.

%Vor%     
Wil P 21.10.2009 20:00
quelle

Tags und Links