2013-08-16 21 views
7

背景:私は、serialPort DataReceivedイベントが発生してからの経過時間を記録するために使用しているタイマーを持っています。私は、クエリを送信して1つの応答を取得する代わりに、データの連続ストリームを取得しているため、組み込みのタイムアウトイベントを使用する代わりに、自分自身の解決策を作成しています。System.Timers.Timer timer.Stop()が呼び出された後に実行される経過イベント

問題: DataReceivedハンドラには、タイマが停止しないようにするためのステートメントがあります。問題は、あとでElapsedハンドラを実行するのに多くの時間がかかることです。

私はこの問題を解決するために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を実行に使用します。ランタイムはTimerをスレッドプールに入れます。 Stopメソッドを呼び出す前に既にキューに入っていました。それは経過時間に発火するでしょう。

この問題を回避するには、Timer.AutoResetをfalseに設定し、必要に応じて経過時間ハンドラでタイマーを開始します。 AutoResetをfalseに設定すると、タイマーは1回だけ起動するので、タイマーを起動するには、手動でタイマーを開始します。

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

tryを最後に追加する理由は何ですか? –

+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 
関連する問題