背景:我有一个计时器,用于跟踪自串行端口数据接收事件被触发以来已经过去了多长时间。我正在为此创建自己的解决方案,而不是使用内置的超时事件,因为我正在获取连续的数据流,而不是发送查询并获取一个响应。
问题:在 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();
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)