2011-11-29 22 views
6

Tengo una aplicación que utiliza temporizadores para ejecutar ocasionalmente tareas de supervisión en subprocesos secundarios. Algunas de estas tareas de limpieza requieren mucho tiempo y me gustaría poder cancelar estas tareas (con gracia si es posible) cuando mi usuario finaliza el programa.¿Puedo detener un System.Threading.Timer

¿Hay alguna manera de abortar el hilo programáticamente como puedo con Thread.Abort(), o tendría que agregar un indicador al código para indicar que el hilo ha terminado y verificar eso en lugares valiosos en el código que se inicia con el temporizador?

+0

¿La terminación de la aplicación no terminaría todos los hilos? – CJ7

Respuesta

4

No hay manera de saber Thread en el que se ejecutará una devolución de llamada Threading.Timer antes de tiempo. Por lo tanto, no hay una forma general de abortarlo. Es posible hacer que la devolución de llamada comunique la instancia Thread pero abre un par de condiciones de carrera

Nota: En general, usar Abort es una mala práctica. Es una forma bastante confiable de terminar con interbloqueos y/o fugas de recursos difíciles de detectar. Es mejor utilizar un mecanismo pasivo como CancellationToken

+0

De nuevo, +1 en males de abortar. –

5

Puede detener el temporizador antes de que se ejecute la devolución de llamada usando .change, pero una vez que la devolución de llamada comienza a ejecutarse debe usar un indicador de nivel de aplicación para permitir que salga su código.

Como nota al margen, no debe usar thread.abort() a menos que esté absolutamente 100% seguro de que conoce el estado en el que se va a dejar. Puede desestabilizar seriamente su aplicación de maneras extrañas.

+0

+1 en evitar Thread.Abort() como la peste ... Ni siquiera permiten Abort() en el TPL. –

1

¿Quiere decir algo en esta línea?

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); primero uso el método .disponer, pero no funciona en mi caso, así que uso Timer.change.

esta es la mejor solución que he encontrado.

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

Explicación: Destruye object = destroy proccess.

+0

En general, las respuestas son mucho más útiles si incluyen una explicación de lo que se pretende que haga el código, y por qué eso resuelve el problema sin introducir otras. (Esta publicación fue marcada por al menos un usuario, presumiblemente porque pensaban que una respuesta sin explicación debería ser eliminada.) –

+0

Explicación: Destruye el objeto = destruye el proceso. –

Cuestiones relacionadas