2009-03-04 18 views
0

Ich brauche ein paar Timer als lokale Variable schaffen so etwas wie zu tun:Wie kann ich verhindern, dass mein Timer vom GC erfasst wird, bevor der Rückruf ausgeführt wird?

void Foo() 
{ 
    Timer t = new Timer(myTimerCallback,null,1000,Timeout.Infinite); 
} 

Leider sind einige von ihnen werden von GC gesammelt, bevor sie myTimerCallback nach 1 Sekunde aufzurufen. Da ich so viele Timer habe, ist es unmöglich, sie in einem privaten statischen Member zu speichern. Und es ist auch schwer einen Platz zu finden, an den man GC.Keeplive (t) stellen kann.

Wie kann ich jeden Timer machen, bevor er stirbt?

+0

Der Grund, warum ich diesen Timer nicht in einem privaten Mitglied speichern möchte, ist, dass es zu viele gibt. Ich kann es versuchen, aber gibt es einen besseren Weg? –

+0

Wenn es zu viele Timer zum Speichern gibt, ist es vielleicht Zeit, einen Schritt zurück zu machen und sich zu fragen, ob Sie das richtige Problem lösen? –

+0

seconding @ Damiens Kommentar. Sie sollten den GC in einer verwalteten Laufzeit nicht bekämpfen. Ich würde vorschlagen, die Kugel zu beißen und die Referenzen zu speichern. Sie werden überrascht sein, wie wenig Auswirkungen es auf die Leistung hat. –

Antwort

1

Sie können sie in einer Sammlung speichern, um einen Verweis zu behalten, und in der Ereignismethode den Verweis aus der Sammlung entfernen. Ich denke, dass Sie den Zustandsparameter verwenden müssen, um den Zeitgeber in der Auflistung zu identifizieren (übergeben Sie einen Verweis auf den Zeitgeber oder einen Schlüssel in der Auflistung als Zustandsparameter in der Anweisung "New Timer").

Bitte beachten Sie, dass die Callback-Funktionen auf anderen Threads ausgeführt werden, so dass Sie mehrere Callback-Funktionen gleichzeitig ausführen können. Verwenden Sie das Sperren, um sicherzustellen, dass Referenzen hinzugefügt/entfernt werden.

2

Ihre beste Wette ist es, sie in einer Mitgliedsvariablen zu speichern und sie dann zu entsorgen, wenn Sie sie nicht mehr benötigen.

1

Speichern Sie sie in einem Element, z. B. List<Timer>.

1

Warum ist es unmöglich, sie zu speichern? Vielleicht können Sie sie einfach aus dieser Sammlung entfernen, wenn ihre Arbeit erledigt ist?

1

Es ist wichtig zu sehen, dass GC.KeepAlive() Ihr Problem nicht lösen kann. Das verlängert die Lebensdauer Ihres Objekts nur auf die Anweisung. Sie müssten so lange Schleife oder Blockieren, wie der Timer am Leben bleiben muss. Beachten Sie auch, dass die Lebensdauer von Referenzen in lokalen Variablen im Debug-Build unterschiedlich ist. Das JIT hält sie bis zum Ende der Methode am Leben, damit die Uhren funktionieren können. Produzieren schwierig "funktioniert im Debug, funktioniert nicht im Release-Modus" Probleme.

Sie müssen einen Life-Verweis auf das Timer-Objekt führen. Das wird typischerweise mit einem Feld in einer Klasse gemacht. Die Lebensdaueranforderungen werden nun an das Klassenobjekt übergeben. Es muss so lange am Leben bleiben, wie der Timer benötigt wird. Normalerweise kein Problem. Wenn dies der Fall ist, müssen Sie die Referenz statisch machen.

Verwandte Themen