2010-05-12 21 views
43

En mi aplicación, tengo que enviar los latidos del corazón periódicamente a una aplicación "hermano".System.Timers.Timer/Threading.Timer vs Thread with WhileLoop + Thread.Sleep para tareas periódicas

Esto se logra mejor con System.Timers.Timer/Threading.Timer o usando un Thread con un while loop y un Thread.Sleep?

El intervalo de latido es 1 segundo.

while(!exit) 
{ 
    //do work 
    Thread.Sleep(1000); 
} 

o

myTimer.Start(() => { 
         //do work 
         }, 1000); //pseudo code (not actual syntax)... 

Respuesta

32

System.Threading.Timer tiene mi voto.

System.Timers.Timer está diseñado para ser utilizado en el servidor (su código se ejecuta como un servidor/servicio en una máquina host en lugar de ser ejecutado por un usuario) funcionalidad del temporizador.

Un subproceso con un ciclo While y un comando Thread.Sleep es realmente una mala idea dada la existencia de meca nismos de temporizador más robustos en .NET.

+2

y usted tiene el mío. – Alan

+2

@ Alan: y usted tiene el mío – abatishchev

+3

La clase System.Timers.Timer realmente se puede utilizar en una aplicación de modo de usuario tan fácilmente como System.Threading.Timer. Internamente, System.Timers.Timer utiliza System.Threading.Timer para su mecanismo de temporización interno, y solo lo ajusta para controlar los problemas de tiempo de diseño ... –

22

Server Timers son una criatura diferente de los hilos de dormir.

Por un lado, en función de la prioridad de su hilo, y qué más se está ejecutando, su hilo de dormir puede o no ser despertado y programado para ejecutarse en el intervalo que solicite. Si el intervalo es lo suficientemente largo, y la precisión de la programación en realidad no importa, Thread.Sleep() es una opción razonable.

Los temporizadores, por otro lado, pueden aumentar sus eventos en cualquier subproceso, lo que permite una mejor capacidad de programación. El costo de usar temporizadores, sin embargo, es un poco más complejo en su código, y el hecho de que tal vez no pueda controlar qué hilo ejecuta la lógica que activa el evento del temporizador. A partir de los documentos: temporizador basado en servidor

El está diseñado para su uso con los subprocesos de trabajo en un entorno multiproceso . Los temporizadores del servidor se pueden mover entre subprocesos a manejar el evento transcurrido elevado, dando como resultado más precisión que Temporizadores de Windows al generar el evento en tiempo.

Otra consideración es que los temporizadores invocan a su delegado de Elapsed en un subproceso de ThreadPool. Dependiendo de cuánto tiempo consuma y/o su lógica sea complicada, es posible que no desee ejecutarlo en el grupo de subprocesos, es posible que desee un subproceso dedicado. Otro factor con los temporizadores es que si el proceso tarda lo suficiente, el evento del temporizador puede volver a plantearse (concurrentemente) en otro subproceso, lo que puede ser un problema si el código que se está ejecutando no está previsto o estructurado para concurrencia.

No se debe confundir servidor temporizadores con "Windows Timers". Lo último generalmente se refiere a los mensajes WM_TIMER que pueden entregarse en una ventana, lo que permite que una aplicación programe y responda al procesamiento temporizado en su hilo principal sin dormir. Sin embargo, Windows Timers también puede hacer referencia al Win API for low-level timing (que no es lo mismo que WM_TIMER).

+0

Gracias por la respuesta. Estoy un poco confundido entre "Temporizadores de servidor" y "Temporizadores de Windows" y cómo eso se relaciona con System.Threading.Timer y Thread.Sleep – Alan

+1

Bien, System.Timers.Timer es un temporizador de servidor. Gotcha! – Alan

+0

En general, es una mala idea perder un hilo completo que en su mayoría estará durmiendo. Los subprocesos son pesados ​​y lo mejor es utilizar una de las alternativas basadas en ThreadPool. –

20

Ni :)

Dormir es típicamente mal visto (por desgracia no puedo recordar los detalles, pero por un lado, es un "bloque" uninteruptible), y Timer s vienen con un montón de equipaje. Si es posible, yo recomendaría System.Threading.AutoResetEvent como tal

// initially set to a "non-signaled" state, ie will block 
// if inspected 
private readonly AutoResetEvent _isStopping = new AutoResetEvent (false); 

public void Process() 
{ 
    TimeSpan waitInterval = TimeSpan.FromMilliseconds (1000); 

    // will block for 'waitInterval', unless another thread, 
    // say a thread requesting termination, wakes you up. if 
    // no one signals you, WaitOne returns false, otherwise 
    // if someone signals WaitOne returns true 
    for (; !_isStopping.WaitOne (waitInterval);) 
    { 
     // do your thang! 
    } 
} 

El uso de un AutoResetEvent (o su primo ManualResetEvent) garantiza un verdadero bloque con señalización segura hilo (por cosas tales como la finalización de precaución anterior). En el peor, es una mejor alternativa a Sleep

Espero que esto ayude :)

+0

Me gusta, la capacidad de cerrar limpiamente el hilo es agradable. –

+6

¿Por qué un bucle for en lugar de while? – gav

+2

@gav, 'while' funciona igual de bien,' for' es una preferencia estilística. –

1

He descubierto que la única aplicación que realmente temporizador escalas es System.Threading.Timer. Todas las otras implementaciones parecen bastante falsas si se trata de una cantidad no trivial de elementos programados.

Cuestiones relacionadas