2013-08-16 43 views
7

Nền: Tôi có bộ hẹn giờ mà tôi đang sử dụng để theo dõi thời gian kể từ khi sự kiện SerialRort DataReceived đã được kích hoạt. Tôi đang tạo giải pháp của riêng mình cho điều này thay vì sử dụng sự kiện hết thời gian chờ được xây dựng bởi vì tôi nhận được luồng dữ liệu liên tục, thay vì gửi một truy vấn và nhận được một phản hồi.System.Timers.Timer Sự kiện đã xảy ra sau khi hẹn giờ.Stop() được gọi là

Sự cố: Trong trình xử lý DataReceived Tôi có tuyên bố ngừng hẹn giờ để không trôi qua. vấn đề là rất nhiều thời gian nó vẫn thực hiện các xử lý sau khi còn sót lại.

Tôi đã đọc có thể sử dụng SynchronizingObject để giải quyết vấn đề này nhưng tôi không chắc chắn cách thực hiện điều đó.

Đây là mã của tôi: Tôi đã cố gắng cắt bỏ mọi thứ mà tôi không nghĩ là có liên quan.

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

    } 

Trả lời

24

Đây là hành vi nổi tiếng. System.Timers.Timer sử dụng nội bộ ThreadPool để thực thi. Thời gian chạy sẽ xếp hàng Timer trong luồng. Nó có thể đã xếp hàng trước khi bạn gọi phương thức Stop. Nó sẽ bắn vào thời gian trôi qua.

Để tránh điều này xảy ra, hãy đặt Timer.AutoReset thành sai và khởi động lại bộ hẹn giờ trong trình xử lý đã qua nếu bạn cần. Đặt AutoReset sai khiến hẹn giờ chỉ kích hoạt một lần, do đó, để có được bộ hẹn giờ được kích hoạt theo khoảng thời gian bắt đầu hẹn giờ bằng tay một cách thủ công.

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 có nhận xét gì không? –

+0

Lý do để thêm thử cuối cùng là gì? –

+5

@mikejames Trong khối 'try' bạn sẽ thêm logic của mình, ngay cả trong trường hợp ngoại lệ' finally' block sẽ đảm bảo rằng yourTimer sẽ bắt đầu lại. –

2

Tôi đã tạm dừng tính giờ với mã này. cho tôi hoạt động.

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 
Các vấn đề liên quan