2012-10-03 20 views
5

Uso C# con Compact Framework 2, SP2.System.Threading.Timer non si avvia?

Il sistema operativo del dispositivo è stato configurato per l'avvio con la mia applicazione, chiamiamo l'applicazione "Loader.exe".

Il caricatore è semplicemente questo: un modulo semplice e semplice che mostra i messaggi di stato durante il caricamento, se necessario (termini generici per l'esistenza di un errore e un messaggio di eccezione o "avvio dell'applicazione [xyz]") e una macchina a stati in esecuzione in background mentre viene visualizzato un modulo di base a schermo intero.

Così il costruttore di forma di Loader ha quanto segue al molto finali:

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; 
} 

E "RunStateMachine" funziona su un thread diverso da quello l'interfaccia utente, permettendo al modulo per visualizzare, e le eventuali esigenze RunStateMachine tempo per interagire con il modulo, come l'aggiornamento dei messaggi, chiamo una funzione che utilizza if (this.InvokeRequired) {this.Invoke (...);} else {...}

Quindi, il mio problema?
Intermittently, il mio programma si bloccherà, ed è perché il timer non ha attivato una richiamata. Ho aggiunto il messaggio di debug nel blocco try sopra, insieme a MOLTE altre posizioni per dirmi dove è stato interrotto, incluso un messaggio all'inizio di "RunStateMachine". Alla fine, il mio programma era appeso al messaggio "Avvio del thread iniziale della GUI ..."

Questo mi dice che il timer del filo non sta eseguendo il tempo uno in cui ne ho bisogno.
La mia teoria è che si sta raccogliendo i rifiuti prima che il timer attivi la richiamata. Ciò significherebbe se il timer fosse globale, e quindi disposto in modo esplicito quando arriverò su RunStateMachine, che funzionerà perfettamente ... ma non voglio pensare di averlo risolto solo per scoprire che questo si presenterà a intermittenza tra un mese da oggi.

Pensieri?

+0

Che cosa significa "sospeso su un messaggio"? Non sembra dichiarazione in cui qualsiasi cosa può rimanere bloccata. –

+0

Non eseguire il debug con le etichette. Cerca System.Diagnostics.Debug.Print() e raccogli maggiori informazioni. –

+0

@ Holen Holterman, la terminologia non è corretta, quindi. "Il programma si ferma perché non sta eseguendo nient'altro, non perché qualcosa sta bloccando." Mi sentivo "appeso" sarebbe più conciso, anche se capisco che ha una connotazione diversa ad esso. Come usare Debug.Stampa invece di etichette: in generale sono d'accordo, anche se non sapevo prima di questo punto in cui l'applicazione si fermava * o * se avessi accesso a ciò che è stato stampato una volta interrotto, avevo bisogno di qualcosa che fosse aggiornato sullo schermo. Grazie per il suggerimento, però. –

risposta

6

La mia teoria è che si tratta di raccolta dei rifiuti prima del timer che attiva il callback. Ciò significherebbe se il timer fosse globale e quindi disposto in modo esplicito quando arrivo a RunStateMachine, che eseguirà perfettamente ... ma non voglio pensare di averlo risolto solo per trovare che arriva a intermittenza di un mese da adesso.

Sembra che vogliate confermare che questo è il vostro problema. Sì, questo è il problema.

Il timer è memorizzato in una variabile locale che non viene mai più utilizzata. Questo lo rende idoneo per GC. Il GC'ing del timer porta alla finalizzazione che porta al timer da disabilitare.

Suggerisco di memorizzare il timer in un campo istanza della classe modulo e rimuoverlo da lì una volta che la richiamata è stata attivata.