Как заблокировать таймер при обработке прошедшего события? - PullRequest
13 голосов
/ 02 мая 2009

У меня есть таймер, который не должен обрабатывать обработчик прошедшего события одновременно. Но обработка одного прошедшего события может мешать другим. Я реализовал приведенное ниже решение, но что-то не так; кажется, что я должен использовать таймер по-другому или использовать другой объект в пространстве потоков. Казалось, таймер подходит лучше всего, потому что мне нужно периодически проверять состояние, но иногда проверка занимает больше времени, чем мой интервал. Это лучший способ подойти к этому?

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

Ответы [ 5 ]

14 голосов
/ 02 мая 2009

Вы можете установить для AutoReset значение false, а затем явно сбросить таймер после того, как закончите его обработку. Конечно, то, как вы справитесь с этим, зависит от того, как вы ожидаете, что таймер будет работать. Выполнение этого способа позволит вашему таймеру отклониться от фактического заданного интервала (как при остановке и перезапуске). Ваш механизм позволил бы запускать каждый интервал и обрабатывать его, но это может привести к отставанию в обработке необработанных событий, которые обрабатываются сейчас, вблизи истечения таймера, который вызывает вызов обработчика.

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();
}
8 голосов
/ 02 мая 2009

Я обычно останавливаю таймер во время его обработки, захожу в блок try / finally и возобновляю таймер после завершения.

1 голос
/ 02 мая 2009

Если LookForItWhichMightTakeALongTime() займет много времени, я бы посоветовал не использовать System.Windows.Forms.Timer, потому что это заблокирует ваш поток пользовательского интерфейса, и пользователь может убить ваше приложение, думая, что оно заморожено.

Вы можете использовать BackgroundWorker (вместе с Timer, если хотите).

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

И вы можете позвонить на номер RunWorkerAsync() из любой точки мира, если хотите, даже с номера Timer. И просто убедитесь, что BackgroundWorker уже запущен, так как вызов RunWorkerAsync() во время его работы вызовет исключение.

private void timer_Tick(object sender, EventArgs e)
{
  if (!backgroundWorker.IsBusy)
    backgroundWorker.RunWorkerAsync();
}
0 голосов
/ 02 мая 2009

Я использую System.Threading.Timer, например,

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



    }
0 голосов
/ 02 мая 2009
timer.enabled = false

или

timer.stop();

и

timer.enabled = true

или

timer.start();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...