System.Timers.Timer在调用timer.Stop()之后执行Elapsed事件

The*_*l26 12 .net c# timer

背景:我有一个计时器,用于跟踪自触发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));

    }
Run Code Online (Sandbox Code Playgroud)

Sri*_*vel 30

这是众所周知的行为.System.Timers.Timer内部ThreadPool用于执行.运行时将Timer在线程池中排队.在调用Stop方法之前它已经排队了.它将在经过的时间开火.

为了避免这种情况发生,设置Timer.AutoReset为false并在已经过的处理程序中重新启动计时器(如果需要).设置为AutoResetfalse会使计时器仅触发一次,因此为了在间隔时间内启动计时器,请再次手动启动计时器.

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();
     }
}
Run Code Online (Sandbox Code Playgroud)

  • @mikejames在`try`块中你将添加你的逻辑,即使在异常的情况下`finally`块也将确保你的theTimer将重新开始. (5认同)
  • @HilalAl-Rajhi `System.Timers.Timer` 有一个名为 `AutoReset` 的属性 (2认同)
  • 这不是在回答问题。问题是如何正确停止计时器,而不是阻止自动重置。 (2认同)