Pregunta

Tengo un temporizador que no necesita procesar su controlador de eventos transcurrido al mismo tiempo. Pero el procesamiento de un evento transcurrido puede interferir con otros. Implementé la siguiente solución, pero algo se siente mal; Parece que debería usar el temporizador de manera diferente o usar otro objeto dentro del espacio de subprocesamiento. El temporizador pareció encajar mejor porque necesito verificar periódicamente un estado, pero a veces la verificación tomará más tiempo que mi intervalo. ¿Es esta la mejor manera de abordar esto?

// member variable
private static readonly object timerLock = new object();
private bool found = false;


// elsewhere
timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
timer.Elapsed = Timer_OnElapsed;
timer.Start();


public void Timer_OnElapsed(object sender, ElapsedEventArgs e)
{
  lock(timerLock)
  {
    if (!found)
    {
      found = LookForItWhichMightTakeALongTime();
    }
  }
}
¿Fue útil?

Solución

Puede establecer AutoReset en falso, luego reiniciar explícitamente el temporizador una vez que haya terminado de manejarlo. Por supuesto, cómo lo maneja realmente depende de cómo espere que funcione el temporizador. Hacerlo de esta manera permitiría que su temporizador se aleje del intervalo especificado real (como si se detuviera y reiniciara). Su mecanismo permitiría que cada intervalo se dispare y se maneje, pero puede resultar en una acumulación de eventos no manejados que se manejan ahora cerca del vencimiento del temporizador que hace que se invoque el controlador.

timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
timer.Elapsed += Timer_OnElapsed;
timer.AutoReset = false;
timer.Start();


public void Timer_OnElapsed(object sender, ElapsedEventArgs e)
{
    if (!found)
    {
      found = LookForItWhichMightTakeALongTime();
    }
    timer.Start();
}

Otros consejos

Por lo general, detengo el temporizador mientras lo estoy procesando, ingrese un bloque try / finally y reanudo el temporizador cuando termine.

Si LookForItWhichMightTakeALongTime () va a tomar mucho tiempo, sugeriría no usar un System.Windows.Forms.Timer porque hacerlo bloqueará su interfaz de usuario y el usuario puede matar su aplicación pensando que se ha congelado.

Lo que podrías usar es un BackgroundWorker (junto con un Timer si así lo deseas).

public class MyForm : Form
{
  private BackgroundWorker backgroundWorker = new BackgroundWorker();

  public MyForm()
  {
    InitializeComponents();
    backgroundWorker.DoWork += backgroundWorker_DoWork;
    backgroundWorker.RunWorkerCompleted +=
                                backgroundWorker_RunWorkerCompleted;
    backgroundWorker.RunWorkerAsync();
  }

  private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
  {
    e.Result = LookForItWhichMightTakeALongTime();
  }

  private void backgroundWorker_RunWorkerCompleted(object sender,
                                             RunWorkerCompletedEventArgs e)
  {
    found = e.Result as MyClass;
  }
}

Y puede llamar a RunWorkerAsync () desde cualquier lugar que desee, incluso desde un Timer si lo desea. Y solo asegúrese de verificar si el BackgroundWorker ya se está ejecutando desde que se llamó a RunWorkerAsync () cuando se está ejecutando, se producirá una excepción.

private void timer_Tick(object sender, EventArgs e)
{
  if (!backgroundWorker.IsBusy)
    backgroundWorker.RunWorkerAsync();
}
timer.enabled = false

o

timer.stop();

y

timer.enabled = true

o

timer.start();

Yo uso System.Threading.Timer como tal

 class Class1
    {
        static Timer timer = new Timer(DoSomething,null,TimeSpan.FromMinutes(1),TimeSpan.FromMinutes(1));

        private static void DoSomething(object state)
        {
            timer = null; // stop timer

            // do some long stuff here

            timer = new Timer(DoSomething, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
        }



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