System.Timers.Timer的已用事件timer.Stop后执行()被调用 [英] System.Timers.Timer Elapsed event executing after timer.Stop() is called

查看:1512
本文介绍了System.Timers.Timer的已用事件timer.Stop后执行()被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景:我有我使用跟踪多久,它一直以来的SerialPort DataReceived事件检索已被解雇的计时器。我创建使用内置的超时事件,因为我得到一个连续的数据流,而不是发送一个查询并获得一个响应我自己解决这个代替。

的问题: 在DataReceived处理我有一份声明停止计时器,这样是不会结束。问题是,很多时候它仍然执行经过的处理程序后记。

我已阅读,是有可能使用到SynchronizingObject的解决这个问题,但我不知道如何做到这一点。

这是我的code:我试图切断一切,我不认为是相关的

 私人System.Timers.Timer的超时;
    私人System.Timers.Timer的updateTimer;

    公共无效启动()
    {
        线程1 =新主题(()=>记录());

        thread1.Start();
    }

    公共无效requestStop()
    {
        this.stop = TRUE;
        this.WaitEventTest.Set();

    }

    私人无效记录()
    {
        TIMEOUT =新System.Timers.Timer的(500); // ** 1.5秒
        updateTimer =新System.Timers.Timer的(500); // ** 1.5秒

        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(); // **消防录像开始事件

        timeOut.Start();
        updateTimer.Start();

        this.waitHandleTest.WaitOne(); // **等待测试结束

        timeOut.Stop();
        updateTimer.Stop();

        comport.Write(COMMAND_COMMANDMODE + Environment.NewLine);
        comport.DiscardInBuffer();
        comport.Close();
        recordingStopTrigger(状态); // **消防录制已停止活动

        stopwatch.Stop();
    }


    // ********** ***********************************
    // **事件处理程序


    私人无效comDataReceived_Handler(对象发件人,SerialDataReceivedEventArgs E)
    {

        双力= -100000;
        字符串TEMP =-100000;

        //timeOut.SynchronizingObject.Invoke(new行动(()=> {timeOut.Stop();}),新的对象[] {发送,E});

        timeOut.Stop();

        // **我在这里打消了我的行动code,让事情变得简单。


        timeOut.Start();
    }

    私人无效TimeOut_Elapsed(对象发件人,System.Timers.ElapsedEventArgs E)
    {
        timeOut.Stop();
        updateTimer.Stop();


        // **火代表了图形用户界面将被倾听,更新图表。
        如果(eventComTimeOut = NULL和放大器;!&安培; this.stop ==假)
        {
            如果(eventComTimeOut(这一点,新eventArgsComTimeOut(comport.PortName,读)))
            {
                //重试= TRUE;
                comport.Write(COMMAND_CONTINUOUSMODE +\ r);
                updateTimer.Start();
                timeOut.Start();
            }
            其他
            {
                this.stop = TRUE;
                //重试= FALSE;
                this.WaitEventTest.Set();
                状态= eventArgsStopped.Status.failed;
            }
        }
    }

    无效updateTimer_Elapsed(对象发件人,System.Timers.ElapsedEventArgs E)
    {

        // **火代表了图形用户界面将被倾听,更新图表。
        名单<阅读>临时=新的名单,其中,阅读与GT;(report.Readings_Force);
        eventNewData(这一点,新eventArgsNewData(临时));

    }
 

解决方案

这是众所周知的行为。 System.Timers.Timer的在内部使用线程池执行。运行时将排队的定时器的线程池。这本来已经排队之前,你有一个名为停止方法。它会自动攻击经过的时间。

要避免这种情况的发生设置 Timer.AutoReset 为false,并启动定时器回到过去的处理程序,如果你需要一个。设置自动复位 false使计时器只一次,所以为了得到计时器所触发的时间间隔手动重新开始计时。

  yourTimer.AutoReset = FALSE;

私人无效Timer_Elapsed(对象发件人,System.Timers.ElapsedEventArgs E)
{
     尝试
     {
         //在此处添加你的逻辑
     }
     最后
     {
         yourTimer.Enabled = TRUE; //或yourTimer.Start();
     }
}
 

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

    }

解决方案

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

这篇关于System.Timers.Timer的已用事件timer.Stop后执行()被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆