2011-11-29 25 views
6

Ho un'applicazione che utilizza i timer per eseguire occasionalmente attività di monitoraggio su thread secondari. Alcune di queste attività di pulizia richiedono molto tempo e vorrei essere in grado di abortire queste attività (con garbo se possibile) quando il mio utente termina il programma.Posso interrompere un System.Threading.Timer

C'è un modo per interrompere il thread in modo programmatico come posso con Thread.Abort(), o dovrei aggiungere un flag al codice per indicare che il thread è terminato e verificarlo in posti valenti nel codice che viene avviato dal timer?

+0

La terminazione dell'app non terminerebbe tutti i thread? – CJ7

risposta

4

Non è possibile conoscere lo Thread su cui verrà eseguita prima una richiamata di Threading.Timer. Quindi non esiste un modo generale per abortire. È possibile che la richiamata stessa comunichi l'istanza Thread ma apre un paio di condizioni di gara

Nota: in generale l'utilizzo di Abort è una cattiva pratica. È un modo abbastanza affidabile per finire con difficoltà a rilevare deadlock e/o perdite di risorse. E 'molto meglio utilizzare un meccanismo passivo come CancellationToken

+0

Ancora, +1 sui mali di abortire. –

5

È possibile interrompere il timer prima che sia richiamata esegue utilizzando .change, ma una volta che la richiamata inizia l'esecuzione è necessario utilizzare una bandiera livello di applicazione per consentire il codice per uscire.

Come nota a margine, non si dovrebbe usare thread.abort() a meno che non si è assolutamente sicuri al 100% che si conosce lo stato che sta per essere lasciato in. Esso può destabilizzare seriamente la vostra applicazione in modo strano.

+0

+1 su evitare Thread.Abort() come la peste ... Non consentono nemmeno Abort() nella TPL. –

1

Intendi qualcosa in questo senso?

using System; 
using System.Threading ; 

class AppCore : IDisposable 
{ 
    Timer TimerInstance ; 
    string[] Args   ; 

    public AppCore(string[] args) 
    { 
     if (args == null) throw new ArgumentNullException("args") ; 
     this.TimerInstance = new Timer(Tick , null , new TimeSpan(0,0,30) , new TimeSpan(0,0,15)) ; 
     this.Args   = args ; 
     this.Cancelled  = false ; 
     this.Disposed  = false ; 
     return ; 
    } 

    public int Run() 
    { 
     // do something useful 
     return 0 ; 
    } 

    private bool Cancelled ; 
    public void Cancel() 
    { 
     lock(TimerInstance) 
     { 
      Cancelled = true ; 
      TimerInstance.Change(System.Threading.Timeout.Infinite , System.Threading.Timeout.Infinite) ; 
     } 
     return ; 
    } 

    private void Tick(object state) 
    { 
     if (!Cancelled) 
     { 
      // do something on each tick 
     } 
     return ; 
    } 

    private bool Disposed ; 
    public void Dispose() 
    { 
     lock (TimerInstance) 
     { 
      if (!Disposed) 
      { 
       using (WaitHandle handle = new EventWaitHandle(false , EventResetMode.ManualReset)) 
       { 
        TimerInstance.Dispose(handle) ; 
        handle.WaitOne() ; 
       } 
       Disposed = true ; 
      } 
     } 
     return ; 
    } 

} 
3

uso this.Timer.Change (Timeout.Infinite, Timeout.Infinite); prima ho usato il metodo .dispose ma non funziona nel mio caso quindi ho usato Timer.change.

questa è la soluzione migliore che ho trovato.

0
public void stopTimer(){ 
    myThreadingTimer = null; 
} 

Explication: Distruggi oggetto = distruggi processo.

+0

In genere, le risposte sono molto più utili se includono una spiegazione di ciò che il codice è destinato a fare e perché questo risolve il problema senza introdurre gli altri. (Questo post è stato contrassegnato da almeno un utente, presumibilmente perché pensava che una risposta senza spiegazione dovesse essere eliminata). –

+0

Explication: Destroy object = destroy proccess. –

Problemi correlati