2014-12-12 2 views
0

Я новичок в C#, и мне нужно было использовать таймер для небольшого приложения, которое я использую для мониторинга части оборудования. Я нашел код для таймера, но использует DoEvents(). Поскольку я запускаю таймер в течение длительного времени, иногда дней и часов, я начал получать переполнение стека. Теперь я понимаю, что DoEvents() вызывает это, и это то, что большинство людей рекомендует использовать. Какую функцию вы бы рекомендовали использовать вместо DoEvents вместо настройки таймера?Timer - альтернативная реализация DoEvents

Мой код:

private void BeginMonitoringClick() { 
{ 
    myTimer.Tick += new EventHandler(TimerEventProcessor); // myTimer declared elsewhere 
    myTimer.Interval = 2000; 
    myTimer.Start(); 

    while(!exitFlag) 
    { 
     Application.DoEvents(); 
    } 
} 

private void TimerEventProcessor(Object myObject, EventArgs myEventArgs){ 
    // Talk to hardware, see if it is doing OK 
} 
+0

Это консольное приложение, и вам просто интересно, как предотвратить его выход? –

+3

Вы можете просто вернуться из 'BeginMonitoringClick()' и таймер должен продолжать работать! (Предполагаю, что у вас есть приложение Windows Forms или WPF) –

+0

@WillEddins, нет, это приложение на основе Windows Forms на основе графического интерфейса. Функция BeginMonitoringClick() на самом деле является обработчиком кнопки, которую я имею в GUI –

ответ

0

Ваш StackOverflowException является возможно вызваны повторными нажатиями кнопки. Это приведет к тому, что метод BeginMonitoringClick() будет называться рекурсивно, что в конечном итоге переполнит стек.

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

Лично я хотел бы, чтобы Microsoft никогда не включала метод DoEvents(), а также его братьев и сестер Control.Refresh() и Control.Update(). Их использование может привести к именно подобным ошибкам, связанным с повторным подключением, и я никогда не видел ситуации, когда их использование действительно требовалось. Всегда есть более подходящее решение.

Как уже отмечалось, чтобы зафиксировать конкретную ошибку в этом коде, вы должны быть в состоянии просто изменить код, удаляя петлю:

private void BeginMonitoringClick() { 
{ 
    myTimer.Tick += TimerEventProcessor; // myTimer declared elsewhere 
    myTimer.Interval = 2000; 
    myTimer.Start(); 
} 

private void TimerEventProcessor(object myObject, EventArgs e) { 
    // Talk to hardware, see if it is doing OK 
} 

Это не ясно, в вашем примере кода, что переменная exitFlag был использован для, поэтому я не могу объяснить альтернативу для этого. Но если он предназначен для приостановки/прекращения мониторинга вашего оборудования, все, что вам действительно нужно сделать, это позвонить по телефону myTimer.Stop() позже, когда вы хотите, чтобы это произошло.

-1

Я рекомендую вам использовать фоновый поток.

var tokenSource = new CancellationTokenSource(); 
     var token = tokenSource.Token; 

     var backgroundTask = Task.Factory.StartNew(() => { 

      while(!token.IsCancellationRequested) 
      { 
       Thread.Sleep(2000); 
       // do work here 
      } 

     } , token); 


     // save your tokenSource somewhere then you can cancel the thread whenever you are done with it. 
     tokenSource.Cancel(); 
Смежные вопросы