System.Timers.Timer Evento transcurrido que se ejecuta después de timer.Stop () se llama

Antecedentes: tengo un temporizador que estoy usando para hacer un seguimiento de cuánto tiempo ha pasado desde que se activó el evento serialPort DataReceived. Estoy creando mi propia solución para esto en lugar de utilizar el evento de tiempo de espera incorporado porque obtengo un flujo continuo de datos, en lugar de enviar una consulta y obtener una respuesta.

El problema: en el manejador DataReceived tengo una instrucción para detener el temporizador para que no pase. el problema es que la mayoría de las veces ejecuta el handheld Transcurrido.

He leído que es posible utilizar SynchronizingObject para resolver este problema, pero no estoy seguro de cómo lograrlo.

Aquí está mi código: traté de eliminar todo lo que no creía relevante.

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 temp = new List(report.Readings_Force); eventNewData(this, new eventArgsNewData(temp)); } 

Este es un comportamiento bien conocido. System.Timers.Timer internamente usa ThreadPool para su ejecución. Runtime pondrá en cola el Timer en threadpool. Ya habría puesto en cola antes de haber llamado al método Stop . Dispara al tiempo transcurrido.

Para evitar que esto ocurra, configure Timer.AutoReset en false y Timer.AutoReset a iniciar el temporizador en el controlador transcurrido si necesita uno. Si se establece la función AutoReset falso, el temporizador se disparará solo una vez, por lo que para activar el temporizador en el intervalo manualmente, inicie el temporizador nuevamente.

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

Hice una pausa en el temporizador con este código. para mí eso funciona

 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