2012-10-03 14 views
5

Ich verwende C# mit Compact Framework 2, SP2.System.Threading.Timer nicht gestartet?

Das Betriebssystem des Geräts wurde eingerichtet, um mit meiner Anwendung zu starten, nennen wir die Anwendung "Loader.exe".

Loader ist einfach dies: eine einzelne, einfache Form, die Statusmeldungen während des Ladevorgangs anzeigt, falls erforderlich (Laienbedingungen für einen Fehler und eine Ausnahmebedingungsnachricht oder "Anwendung starten [xyz]") und eine Zustandsmaschine läuft im Hintergrund, während ein einfaches Vollbild angezeigt wird.

So Konstrukteurs-Loader des Formular hat Folgendes an den sehr Ende:

try 
{ 
    label1.Text = "Starting GUI Init Thread..."; //debug only message 
    System.Threading.Timer guiInit = new System.Threading.Timer(
     RunStateMachine, null, 2000, System.Threading.Timeout.Infinite 
     ); 
    //callback: RunStateMachine, null argument 
    //initial callback is 2000ms from this point, and doesn't run again. 
} 
catch (Exception ex1) 
{ 
    label1.Text = "GUI Init Error 2"; 
    Failure_Label.Text = ex1.Message; 
} 

Und „RunStateMachine“ funktioniert auf einem anderen Thread als die Benutzeroberfläche, so dass das Formular anzuzeigen, und zu jeder Zeit RunStateMachine Bedürfnisse Um mit dem Formular zu interagieren, wie das Aktualisieren von Nachrichten, rufe ich eine Funktion auf, die if (this.InvokeRequired) {this.Invoke (...);} else {...} verwendet

Also, mein Problem?
Von Zeit zu Zeit hängt mein Programm, und es ist, weil der Timer keinen Rückruf ausgelöst hat. Ich habe die debug-Nachricht oben im try-Block hinzugefügt, zusammen mit VIELEN anderen Orten, um mir zu sagen, wo es aufgelegt hat, einschließlich einer Nachricht beim SEHREN Start von "RunStateMachine". Schließlich hing mein Programm an der Meldung "Start GUI Init Thread ..."

Das sagt mir, dass der Thread-Timer nicht läuft eine Zeit ich brauche es.
Meine Theorie ist, dass es Müll gesammelt wird, bevor der Timer den Rückruf auslöst. Das würde bedeuten, wenn der Timer global wäre und dann explizit bei RunStateMachine entsorgt würde, dass es perfekt läuft ... aber ich möchte nicht glauben, dass ich es gelöst habe, nur um zu sehen, dass es in einem Monat intermittierend kommt.

Gedanken?

+0

Was bedeutet "hängen an einer Nachricht"? Sieht nicht wie Aussage aus, wo irgendetwas stecken bleiben kann. –

+0

Debuggen Sie nicht mit Etiketten. Suchen Sie nach System.Diagnostics.Debug.Print() und sammeln Sie weitere Informationen. –

+0

@Henk Holterman, dann ist die Terminologie falsch. "Das Programm stoppt, weil es nichts anderes mehr ausführt, nicht weil irgendetwas blockiert." Ich dachte, "hängen" wäre prägnanter, obwohl ich verstehe, dass es eine andere Bedeutung hat. Zur Verwendung von Debug.Drucken statt Etiketten: Im Allgemeinen stimme ich zu, obwohl ich vorher nicht wusste, wo die Anwendung gestoppt wurde * oder * wenn ich Zugang zu dem hatte, was gedruckt wurde, nachdem es gestoppt wurde, brauchte ich etwas, das auf dem Bildschirm aktualisiert wurde. Danke für den Tipp. –

Antwort

6

Meine Theorie ist, dass es Müll gesammelt vor dem Timer Auslösen des Rückrufs ist. Das würde bedeuten, wenn der Timer global wäre, und dann explizit bei RunStateMachine entsorgt würde, dass es perfekt laufen wird ... aber ich will nicht denken, dass ich es gelöst habe, nur dieses Kommendes stündlich einen Monat zu finden in.

Es sieht so aus, als ob Sie die Bestätigung möchten, dass dies Ihr Problem ist. Ja, das ist das Problem.

Der Timer wird in einer lokalen Variablen gespeichert, die nie wieder verwendet wird. Dies macht es für GC geeignet. Das GC'ing des Timers führt zur Finalisierung, die dazu führt, dass der Timer deaktiviert wird.

Ich schlage vor, Sie speichern den Timer in einem Instanzfeld Ihrer Formularklasse und entfernen Sie es von dort, sobald der Rückruf ausgelöst hat.