Pergunta

Eu tenho um temporizador que as necessidades não processar seu manipulador de eventos decorrido ao mesmo tempo. Mas o processamento de um evento decorrido pode interferir com os outros. Implementei o abaixo solução, mas algo parece errado; parece que tanto eu deveria estar usando o timer de forma diferente ou usando outro objeto dentro do espaço de threading. O temporizador parecia se encaixar melhor porque eu faço necessidade de verificar periodicamente para um status, mas às vezes a verificação vai demorar mais tempo do que o meu intervalo. É esta a melhor maneira de abordar isso?

// 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();
    }
  }
}
Foi útil?

Solução

Você pode definir AutoReset para falsa, então redefinir explicitamente o temporizador depois de ter manuseá-lo. Claro que, como você lida com isso realmente depende de como você espera que o temporizador para operar. Fazendo dessa forma, seria permitir que o seu temporizador para se afastar do intervalo especificado real (como iria parar e reiniciar). Seu mecanismo permitiria que cada intervalo de fogo e ser tratada, mas pode resultar em um acúmulo de eventos sem tratamento que são tratados agora onde perto da expiração do temporizador que causa o manipulador a ser chamado.

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();
}

Outras dicas

Eu costumo parar o temporizador enquanto processá-lo, digite um / finally bloco try, e retomar o temporizador quando terminar.

Se LookForItWhichMightTakeALongTime() vai levar um longo tempo, eu não iria sugerir usando um System.Windows.Forms.Timer porque isso irá travar o seu segmento interface do usuário eo usuário pode matar o seu pensamento aplicação que tem congelado.

O que você pode usar é um BackgroundWorker (juntamente com uma Timer se assim o desejar).

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;
  }
}

E você pode chamar RunWorkerAsync() de qualquer lugar que você quiser, mesmo a partir de um Timer se quiser. E apenas certifique-se de verificar se o BackgroundWorker estiver em execução desde chamando RunWorkerAsync() quando está funcionando irá lançar uma exceção.

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

ou

timer.stop();

e

timer.enabled = true

ou

timer.start();

Eu uso o System.Threading.Timer como assim

 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top