Background: I have a timer that I am using to keep track of how long it has been since the serialPort DataReceived event has been fired. I am creating my own solution to this instead of using the built in timeout event because I am getting a continuous stream of data, instead of sending a query and getting one response.
The Problem: In the DataReceived handler I have a statement to stop the timer so that is doesn't elapse. the problem is that a lot of the time it still executes the Elapsed handler afterword.
I have read that is is possible to use SynchronizingObject to solve this problem but I am not sure how to accomplish that.
Here is my code: I tried to cut out everything that I didn't think was relevant.
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));
}
Elapsed time is the amount of time that passes from the start of an event to its finish. In simplest terms, elapsed time is how much time goes by from one time (say 3:35pm) to another (6:20pm). An important tool that goes hand and hand with elapsed time is the clock.
It would have already queued before you have called Stop method. It will fire at the elapsed time. To avoid this happening set Timer. AutoReset to false and start the timer back in the elapsed handler if you need one.
The System. Timers. Timer class has the same resolution as the system clock. This means that the Elapsed event will fire at an interval defined by the resolution of the system clock if the Interval property is less than the resolution of the system clock.
This is well known behavior. System.Timers.Timer
internally uses ThreadPool
for execution. Runtime will queue the Timer
in threadpool. It would have already queued before you have called Stop
method. It will fire at the elapsed time.
To avoid this happening set Timer.AutoReset
to false and start the timer back in the elapsed handler if you need one. Setting AutoReset
false makes timer to fire only once, so in order to get timer fired on interval manually start timer again.
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();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With