2010-03-12 13 views
10

Estamos obteniendo el siguiente problema al usar System.Threading.Timer (.NET 2.0) desde un servicio de Windows.C# temporizador que se dispara antes de su intervalo de tiempo

  1. hay alrededor de 12 diferentes objetos de temporizador ..
  2. Cada temporizador tiene su debido tiempo e intervalo. Esto está configurado correctamente.
  3. Se observa que después de 3 a 4 horas, los temporizadores comienzan a señalar antes de que transcurra su intervalo. Por ejemplo, si se supone que el cronómetro señala a las 4:59:59, se señala a las 4:59:52, 7 segundos antes.

¿Puede alguien decirme cuál es la causa de este comportamiento y cuál es la solución para eso?

Gracias, Swati

Respuesta

0

Tal re-programación se realiza después de una operación que toma algunos segundos para completar. ¿O no controlas esto?

0

Esto no se puede controlar, ya que depende de la velocidad del sistema; si tiene supercomputadora, puede que no haya suficiente diferencia, pero si tiene PC normal, habrá una diferencia en el intervalo del temporizador después de mucho ejecución.

Espero que ayude.

9

Gran pregunta ... y aquí está la razón:

"Timing" es una cosa difícil cuando se trata de ordenadores ... Nunca se puede garantiza un "intervalo" para ser perfecto. Algunas computadoras "marcan" el temporizador solo cada 14 a 15 milisegundos, algunas más frecuentemente que eso, algunas con menos frecuencia.

Así:

Thread.Sleep(1); 

puede tomar desde 1 a 30 milisegundos para funcionar.

En su lugar, si necesita un temporizador más preciso, tiene que capturar el DateTime de cuando comienza, y luego en sus temporizadores debería comprobar restando DateTime.Now y su hora original para ver si es " tiempo para ejecutar "tu código".

Aquí hay un código de ejemplo de lo que tiene que hacer:

DateTime startDate = DateTime.Now; 

A continuación, se inicia el temporizador con el intervalo establecido en 1 milisegundo. Luego, en su método:

if (DateTime.Now.Subtract(startDate).TotalSeconds % 3 == 0) 
{ 
    // This code will fire every 3 seconds. 
} 

Ese código de arriba disparará fielmente cada 3 segundos. Puede dejarlo funcionando durante 10 años, y aún se disparará cada 3 segundos.

+0

Sé que es solo un ejemplo, pero ¿no aumentaría el intervalo del temporizador a algo así como 100 o incluso 500 mseg? Sé que podrías perder un poco de precisión, pero ¿no sería mejor que disparar un temporizador 1000 veces por segundo cuando solo necesitas resultados cada 3 segundos? –

6

La explicación de Timothy es convincente, pero System.Threading.Timer ya funciona de esta manera. Al menos en la implementación de Rotor, usa el valor devuelto por GetTickCount() para calcular cuándo vence la siguiente devolución de llamada. No es muy probable que el CLR real también lo haga, es más probable que use CreateTimerQueueTimer(). Sin embargo, es probable que esta función API dependa de la marca interna incrementada por la interrupción de marcación del reloj.

En cuestión de qué tan bien funciona el reloj interno (como lo devuelven GetTickCount() y Environment.TickCount) permanece sincronizado con el tiempo de pared absoluto (como lo devuelve DateTime.Now). Lamentablemente, se trata de un detalle de implementación de HAL en su máquina, la capa de abstracción de hardware. El fabricante de la máquina puede proporcionar un HAL personalizado, uno que se ajustó para funcionar con el BIOS y el conjunto de chips de la máquina.

Me gustaría tener problemas si la máquina tiene dos fuentes de sincronización, un chip de reloj que fue diseñado para rastrear el tiempo de pared y sigue funcionando incluso desenchufando la potencia de la máquina, y otra frecuencia disponible en el chipset que puede dividirse en proporcionar la interrupción del reloj. La PC original de IBM AT funcionó de esa manera. Por lo general, se puede confiar en el chip del reloj, el reloj estaría muy apagado si no es preciso. El chipset no puede, cortar las esquinas de la calidad de los osciladores es una manera fácil de ahorrar un centavo.

Resuelva su problema evitando períodos largos en su temporizador y recalculando el próximo tiempo de vencimiento desde DateTime.Now en la devolución de llamada.

+0

Gracias por su ayuda. El nuevo cálculo de los temporizadores puede resolver mi problema. Voy a intentar eso. Gracias una vez más !! –

Cuestiones relacionadas