[英]Is it possible to produce an example of firing Elapsed event of System.Timers.Timer after the Timer has been disposed?
[英]System.Timers.Timer Elapsed event executing after timer.Stop() is called
背景:我有一個計時器,用於跟蹤自觸發serialPort DataReceived事件以來已經過了多長時間。 我正在創建自己的解決方案,而不是使用內置的超時事件,因為我獲得了連續的數據流,而不是發送查詢並獲得一個響應。
問題:在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));
}
這是眾所周知的行為。 System.Timers.Timer
內部使用ThreadPool
執行。 運行時將在線程池中對Timer
進行排隊。 在調用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();
}
}
我用這段代碼暫停了計時器。 對我有用。
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
有同樣的問題,並在一些嘗試結束時使用計時器對象為null並用新的計時器對象替換它的計時器變量修復了該問題。 我知道它的資源很多。 但它解決了這個問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.