2013-08-16 2 views
7

Фон: У меня есть таймер, который я использую, чтобы отслеживать, сколько времени прошло с момента запуска события serialPort DataReceived. Я создаю свое собственное решение для этого вместо использования встроенного события таймаута, потому что я получаю непрерывный поток данных, вместо того, чтобы отправлять запрос и получать один ответ.System.Timers.Timer Истекшее событие, выполняемое после таймера.Stop() называется

Проблема: В обработчике DataReceived у меня есть заявление, чтобы остановить таймер, так что это не истечь. проблема заключается в том, что он много раз выполняет повторное завершение обработчика Истекшего обработчика.

Я читал, что можно использовать SynchronizingObject для решения этой проблемы, но я не уверен, как это сделать.

Это мой код: Я попытался вырезать все, что, как я думаю, не имеет отношения к делу.

private System.Timers.Timer timeOut; 
    private System.Timers.Timer updateTimer; 

    public void start() 
    { 
     thread1 = new Thread(() => record()); 

     thread1.Start(); 
    } 

    public void requestStop() 
    { 
     this.stop = true; 
     this.WaitEventTest.Set(); 

    } 

    private void record() 
    { 
     timeOut = new System.Timers.Timer(500); //** .5 Sec 
     updateTimer = new System.Timers.Timer(500); //** .5 Sec 

     timeOut.Elapsed += TimeOut_Elapsed; 
     updateTimer.Elapsed += updateTimer_Elapsed; 
     updateTimer.AutoReset = true; 


     comport.Open(); 
     comport.DiscardInBuffer(); 


     comport.Write(COMMAND_CONTINUOUSMODE + "\r"); 

     stopwatch.Reset(); 
     stopwatch.Start(); 

     recordingStartTrigger(); //** Fire Recording Started Event 

     timeOut.Start(); 
     updateTimer.Start(); 

     this.waitHandleTest.WaitOne(); //** wait for test to end 

     timeOut.Stop(); 
     updateTimer.Stop(); 

     comport.Write(COMMAND_COMMANDMODE + Environment.NewLine); 
     comport.DiscardInBuffer(); 
     comport.Close(); 
     recordingStopTrigger(status); //** Fire Recording Stopped Event 

     stopwatch.Stop(); 
    } 


    //*********************************************************************************** 
    //** Events Handlers 


    private void comDataReceived_Handler(object sender, SerialDataReceivedEventArgs e) 
    { 

     double force = -100000; 
     string temp = "-100000"; 

     //timeOut.SynchronizingObject.Invoke(new Action(()=> {timeOut.Stop();}), new object[] {sender, e}); 

     timeOut.Stop(); 

     //** I removed my action code here, keep things simple. 


     timeOut.Start(); 
    } 

    private void TimeOut_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     timeOut.Stop(); 
     updateTimer.Stop(); 


     //** fire delegate that GUI will be listening to, to update graph. 
     if (eventComTimeOut != null && this.stop == false) 
     { 
      if (eventComTimeOut(this, new eventArgsComTimeOut(comport.PortName, "READ"))) 
      { 
       //retry = true; 
       comport.Write(COMMAND_CONTINUOUSMODE + "\r"); 
       updateTimer.Start(); 
       timeOut.Start(); 
      } 
      else 
      { 
       this.stop = true; 
       //retry = false; 
       this.WaitEventTest.Set(); 
       status = eventArgsStopped.Status.failed;      
      } 
     } 
    } 

    void updateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 

     //** fire delegate that GUI will be listening to, to update graph. 
     List<Reading> temp = new List<Reading>(report.Readings_Force); 
     eventNewData(this, new eventArgsNewData(temp)); 

    } 

ответ

24

Это хорошо известное поведение. System.Timers.Timer внутренне использует ThreadPool для выполнения. Runtime будет стоять в очереди Timer в threadpool. Он уже поставил бы в очередь до того, как вы вызвали метод Stop. Он будет срабатывать в прошедшее время.

Чтобы избежать этого, установите Timer.AutoReset в значение false и запустите таймер обратно в обработанном обработчике, если он вам нужен. Значение AutoReset false позволяет таймеру срабатывать только один раз, поэтому для того, чтобы таймер снова запускался с интервалом, вручную запускайте таймер.

yourTimer.AutoReset = false; 

private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
{ 
    try 
    { 
     // add your logic here 
    } 
    finally 
    { 
     yourTimer.Enabled = true;// or yourTimer.Start(); 
    } 
} 
+2

@ Downvoter какой-либо комментарий? –

+0

В чем причина добавления попытки? –

+5

@mikejames В блоке 'try' вы добавите свою логику, даже в случае исключений блок' finally' гарантирует, что вашTimer запустится снова. –

2

Я сделал паузу по таймеру с помощью этого кода. для меня это работает.

Private cTimer As New System.Timers.Timer 
Private Sub inittimer() 
    cTimer.AutoReset = True 
    cTimer.Interval = 1000 
    AddHandler cTimer.Elapsed, AddressOf cTimerTick 
    cTimer.Enabled = True 
End Sub 

Private Sub cTimerTick() 
    If cTimer.AutoReset = True Then 
     'do your code if not paused by autoreset false 
    End If 
End Sub 
Смежные вопросы