2009-07-07 53 views
42

Estoy ejecutando un servicio de Windows y utilizando un bucle y Thread.Sleep para repetir una tarea, ¿sería mejor utilizar un método de temporizador?C# Timer o Thread.Sleep

Si es un ejemplo de código sería grande

actualmente estoy usando este código para repetir

int curMinute; 
int lastMinute = DateTime.Now.AddMinutes(-1).Minute; 

while (condition) 
{ 
    curMinute = DateTime.Now.Minute; 

    if (lastMinute < curMinute) { 
     // do your once-per-minute code here 
     lastMinute = curMinute; 
    } 

    Thread.Sleep(50000);  // sleeps for 50 seconds 

    if (error condition that would break you out of this) { 
     break;  // leaves looping structure 
    } 
} 

Respuesta

30
class Program 
{ 
    static void Main(string[] args) 
    { 
     Timer timer = new Timer(new TimerCallback(TimeCallBack),null,1000,50000); 
     Console.Read(); 
     timer.Dispose(); 
    } 

    public static void TimeCallBack(object o) 
    { 
     curMinute = DateTime.Now.Minute; 
     if (lastMinute < curMinute) { 
     // do your once-per-minute code here 
     lastMinute = curMinute; 
    } 
} 

El código podría parecerse a algo como la de arriba

+5

Tenga en cuenta que el temporizador puede estar sujeto a paradas adicionales del sistema o cargas elevadas que la suspensión podría no tener. Esto debe ser considerado en la implementación de cualquier persona. –

11

Es importante entender que el código va a dormir durante 50 segundos entre que termina un bucle, y el arranque el siguiente ...

Un temporizador llamará a su bucle cada 50 segundos, que no es exactamente lo mismo.

Ambos son válidos, pero es probable que lo que estás buscando sea un temporizador.

4

Sí, usar un temporizador liberará un hilo que actualmente está pasando la mayor parte del tiempo durmiendo. Un temporizador también disparará con mayor precisión cada minuto, por lo que probablemente ya no necesite realizar un seguimiento de lastMinute.

42

Un temporizador es una mejor idea, IMO. De esta forma, si se le pide a su servicio que se detenga, puede responder a eso muy rápidamente, y simplemente no volver a llamar al controlador de tictac del temporizador ... si está durmiendo, el administrador del servicio tendrá que esperar 50 segundos o matar a su hilo, ninguno de los cuales es terriblemente agradable.

+16

Para evitar la muerte de la rosca, se puede utilizar un ManualResetEvent.WaitOne (50000) en lugar que un Thread.Sleep(). Luego puede establecer() el identificador de espera para indicar que el subproceso finalizará en la primera conveniencia. Sin embargo, un temporizador probablemente sería preferible en este caso. – Thorarin

2

No es responder a la pregunta, pero en lugar de tener

if (error condition that would break you out of this) { 
     break;  // leaves looping structure 
    } 

Probablemente debería tener

while(!error condition) 

Además, me gustaría ir con un Timer.

0

Puede usar cualquiera de los dos. Pero creo que Sleep() es fácil, claro y más corto de implementar.

7

Tenga en cuenta que llamar Sleep() se congelará el servicio, por lo que si se solicita el servicio de parar, no va a reaccionar durante la duración de la Llamada de sueño()

1

Necesité un hilo para disparar una vez por minuto (see question here) y ahora he usado un DispatchTimer según las respuestas que recibí.

Las respuestas proporcionan algunas referencias que pueden serle de utilidad.

+0

+1 es el primero en mencionar DispatchTimer – LamonteCristo

0

Estoy de acuerdo, usar un temporizador es la mejor opción. Intenté una solución similar a la tuya en el pasado y comencé a tener problemas en los que el ciclo fallaría, y tendría que esperar otro Thread.Sleep() antes de que volviera a disparar. Además, causó todo tipo de problemas al detener el servicio, recibía errores constantes sobre cómo no respondía y tenía que cerrarse.

@ El código de Prashanth debería ser exactamente lo que necesita.

1

He usado ambos temporizadores y Thread.Sleep (x), o cualquiera, dependiendo de la situación.

Si tengo un código corto que necesita ejecutarse repetidamente, probablemente use un temporizador.

Si tengo un fragmento de código que podría demorar más en ejecutarse que el temporizador de retardo (como recuperar archivos de un servidor remoto a través de FTP, donde no controlo o conozco la demora de la red o los tamaños/conteos de archivos) , Esperaré un período de tiempo fijo entre ciclos.

Ambos son válidos, pero como se señaló anteriormente, ellos hacen cosas diferentes. El temporizador ejecuta su código cada x milisegundos, incluso si la instancia anterior no ha finalizado. The Thread.Sleep (x) espera durante un período de tiempo después de completar cada iteración, por lo que la demora total por ciclo siempre será más larga (quizás no mucho) que el período de reposo.

+1

+1 para señalar que cuando se usa un temporizador, el código _debería ejecutarse varias veces al mismo tiempo. – flocki

+0

Podría, a menos que use un semáforo. – Casey

-1

Tendría que decir que dormir es una mejor implementación con una máquina de estado detrás. Esto aún te mantendrá en control de la aplicación en todo momento, pero permitiendo cualquier respuesta necesaria en cualquier momento específico. Esto también se encargará de las rutinas de temporización que son más cortos que el "tiempo de ejecución de procesamiento en el bucle"

Por ejemplo ..

<!-- language: c# --> 
public enum State 
{ 
    Idle = 0, 
    Processing = 1, 
    Stop = 100, 
} 
public void Run() 
{ 
    State state = State.Idle; // could be a member variable, so a service could stop this too 

    double intervalInSeconds = 60; 
    System.DateTime nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds); 
    while (state != State.Stop) 
    { 
     switch (state) 
     { 
      case State.Idle: 
       { 
        if (nextExecution > System.DateTime.Now) 
        { 
         state = State.Processing; 
        } 
       } 
       break; 
      case State.Processing: 
       { 
        // do your once-per-minute code here 

        // if you want it to stop, just set it state to stop. 
        // if this was a service, you could stop execution by setting state to stop, also 
        // only time it would not stop is if it was waiting for the process to finish, which you can handle in other ways 

        state = State.Idle; 
        nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds); 
       } 
       break; 
      default: 
       break; 
     } 

     System.Threading.Thread.Sleep(1); 
    } 
} 
+1

Y qué ventaja sientes que dormir agrega el uso de un temporizador. Un número de otros han dado desventajas de dormir que usted no ha abordado. – Servy

+0

mi ángulo es mantener el control en la aplicación en todo momento, un temporizador de suspensión y/o largo no le permitirá procesar las cosas en intervalos más pequeños que el período de espera seleccionado. – Cr4t3r

+2

Eso es un problema con una implementación 'Sleep 'ingenua, que mejora. Ni siquiera es un problema en una solución basada en 'Timer'; no define un intervalo de espera, define un intervalo de cuándo disparar el evento, por lo que no es necesario hacer nada de este asunto para determinar cuánto tiempo esperar. – Servy