Pregunta

Tengo un temporizador como se define a continuación.El temporizador ejecuta una tarea de larga duración.El problema que tengo es cuando el temporizador está ejecutando el intervalo ha transcurrido nuevamente y otra ejecución del temporizador comienza a I.e _timer_Elapsed.¿Cómo puedo obtener el temporizador para ejecutar un intervalo después de que el temporizador haya terminado?La forma en que ahora puede haber que las ejecuciones de múltiples temporizadores ocurren a la vez y eso causa todo tipo de problemas con mi código.

protected override void OnStart(string[] args)
        {

           _timer = new System.Timers.Timer();
           _timer.AutoReset = false;
           _timer.Interval = (Convert.ToInt32(ConfigurationManager.AppSettings["CheckInterval"]));
           _timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
           _timer.Enabled = true;
           _timer.Start(); // Start timer 

        }


 public static void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                _timer.Interval = (Convert.ToInt32(ConfigurationManager.AppSettings["CheckInterval"])); 

                BLLGenericResult SystemCheckItems_Result = ServiceItemOperations.CheckItems(); // Long Running Task

            }
            catch (Exception ex)
            {
                // Exception handling...
            }
            finally
            {
                _timer.Start();
            }
        }

¿Fue útil?

Solución

Vamos a escribir esto correctamente. Es la asignación de intervalo que te está metiendo en problemas. Un programa de muestra que demuestra el problema:

using System;

class Program {
    static System.Timers.Timer timer;
    static void Main(string[] args) {
        timer = new System.Timers.Timer();
        timer.AutoReset = false;
        timer.Interval = 1000;
        timer.Elapsed += timer_Elapsed;
        timer.Start();
        Console.ReadLine();
    }

    static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
        timer.Interval = 1000;
        Console.WriteLine("Tick");
    }
}

Salida:

Tick
Tick
Tick
...

Retire la asignación de intervalo en el controlador de eventos transcurridos para ver la diferencia.

Entonces, en otras palabras, a pesar de que la propiedad Autoreset es FALSO , simplemente asignar la propiedad del intervalo es suficiente para que el temporizador se reinicie. Gran sorpresa, por supuesto, nadie ve que venga. Y juega estragos en su programa porque asigna la propiedad del intervalo temprano, antes de usted comienza a hacer el levantamiento pesado. Por lo tanto, el evento transcurrido se elevará de nuevo, en otro hilo, mientras que su anterior no haya completado la ejecución. Ese es un error de roscado que está a la espera de suceder, especialmente si su valor de intervalo es demasiado pequeño. Tendrá que asignarlo más tarde, hágalo dentro del bloque finalmente . Es bueno que hiciste el intervalo demasiado pequeño, muy difícil de diagnosticar más tarde.

¿Es este un error C #?

El idioma C # está fuera del gancho, este es un error de .NET Framework. System.Timers.Timer es en general, simplemente no es una clase muy buena, tiene la usabilidad de una motosierra sin un interruptor de seguridad. Estaba destinado a hacer que el sistema. Tienda. Timer clase más utilizable, en particular resolviendo un problema con el hábito de ser basura recolectado demasiado pronto. Un problema resuelto, pero se agregaron tres nuevos problemas. Esto se remonta a .NET 1.0, una versión marco con ruedas de entrenamiento. Simplemente no pueden arreglarlo, se romperá demasiado código existente. Realmente estás mejor con el sistema.Trading.Timer, solo asegúrese de mantener el objeto al que se hace referencia en una variable. Como que ya lo haces.

Otros consejos

A Actualización de 2017:

Hay una nueva herramienta que puede ser útil con este tipo de problemas.

await Task.Delay(TimeSpan.FromSeconds(x)); 

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top