2013-08-16 18 views
7

Arkaplan: serialPort DataReceived olayı tetiklendiğinden beri ne kadar süre olduğunu görmek için kullanıyorum. Yerleşik zaman aşımı olayını kullanmak yerine kendi çözümümü oluşturuyorum çünkü bir sorgu göndermek ve bir yanıt almak yerine sürekli bir veri akışı alıyorum.System.Timers.Timer timer.Stop() çağrıldıktan sonra geçen olay

Sorun: DataReceived eylemcisinde Zamanlayıcıyı durdurmak için zaman aşımını durduracak bir deyim var. Sorun şu ki, Elapsed işleyicisinden bir süre sonra hala devam ediyor.

Bu sorunu çözmek için SynchronizingObject kullanmanın mümkün olduğunu okudum, ancak bunu nasıl gerçekleştireceğimi bilmiyorum.

İşte kodum: İlgili olduğunu düşündüğüm her şeyi kesmeye çalıştım.

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

    } 

cevap

24

Bu iyi bilinen bir davranıştır. System.Timers.Timer, yürütme için dahili olarak ThreadPool kullanır. Çalışma zamanı Timer iş parçacığında sıraya girecek. Stop yöntemini çağırmadan önce zaten sıraya girmiş olurdu. Geçen sürede patlayacaktır.

Bu olmasından kaçınmak için, Timer.AutoReset yanlış ayarını yapın ve gerektiğinde zamanlayıcıyı tekrar başlatıcıya başlatın. AutoReset parametresinin ayarlanması, zamanlayıcının yalnızca bir kez ateşlenmesini sağlar, böylece zamanlayıcıyı ateşe almak için zamanlayıcıyı tekrar başlatmaya başlar.

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 any comment? –

+0

Son olarak denemenin eklenmesinin nedeni nedir? –

+5

@mikejames 'try' bloğunda, istisnasanız bile mantığınızı ekleyeceksiniz, 'son' bloğunuz, yourTimer'in yeniden başlayacağından emin olacak. –

2

Bu kodla zamanlayıcıda bir duraklama yaptım. Benim için bu işe yarıyor.

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 
İlgili konular