停止后,C#计时器运行时间仍稍长

停止后,C#计时器运行时间仍稍长,c#,timer,C#,Timer,我正在使用windows窗体。我正在使用System.Timers.Timer。虽然我用timer.Stop()停止了计时器,但它仍然会继续运行。我放了一些布尔变量来防止这种情况,但没有运气。有人知道这件事吗? 多谢各位 timer = new System.Timers.Timer(); timer.Elapsed += OnTimedEvent; timer.Interval = 1000; ti

我正在使用windows窗体。我正在使用
System.Timers.Timer
。虽然我用
timer.Stop()
停止了计时器,但它仍然会继续运行。我放了一些布尔变量来防止这种情况,但没有运气。有人知道这件事吗? 多谢各位

            timer = new System.Timers.Timer();
            timer.Elapsed += OnTimedEvent;
            timer.Interval = 1000;
            timer.start();

public void cancelConnectingSituation(Boolean result)
        {
            connecting = false;
            timer.Stop();
            if (result)
            {
                amountLabel.Text = "Connected";
            } 
            else
            {
                amountLabel.Text = "Connection fail";
            }
        }


private void OnTimedEvent(Object source, ElapsedEventArgs e)
        {
            if (device.position == 2 && connecting)
            {
                refreshTime();
                setConnectingText();
            }
            else if (connecting)
            {
                setConnectingText();
            }
            else
            {
                refreshTimeAndAmount();
            }
        }

当触发
System.Timers.Timer
已用事件时,将在后台
ThreadPool
线程上触发该事件。这意味着,在调用
Stop
时,可能已经触发了一个事件,并且该线程已排队等待执行

如果要确保事件在停止计时器后不会触发,则需要(除布尔变量外)一个锁:

或者更简单一点:

 readonly object _lock = new object();

 void Stop()
 {
     lock (_lock)
     {
         _timer.Enabled = false; // equivalent to calling Stop()
     }
 }

 void Timer_Elapsed(...) 
 {
     lock (_lock)
     {
         if (!_timer.Enabled)
             return;

         // do stuff
     }
 }

请包括您的计时器代码、启动计时器代码和停止计时器代码。现在,您的问题的答案是“这是因为您的代码中有一个错误”,但如果不看到有错误的代码,我们将无法帮助您修复该错误。@a-f-a您能显示您的代码吗请显示a-否则我们基本上只能猜测。
timer.Interval=1行告诉计时器以1毫秒的间隔启动。那条线的意义是什么?在停止计时器之前执行此操作是一种让一个或多个事件快速连续触发的简单方法。您能否详细说明(作为对问题的编辑)什么是“它仍然继续一点”的意思。目前还不清楚您希望它做什么。例如,如果计时器位于<代码>刷新时间()/代码>,并且调用“代码>计时器.Stutter())/代码>,您是否期望<代码> SETCONTIONTION()/代码>不被调用?@ AF—A:现在您已经发布了代码,我建议您删除设置“代码>间隔< /代码>到<代码> 1 < /COD>(1毫秒)的行。如果你试图停止计时器,那就没有意义了。我有一个确切的问题,我实现了同样的问题。但我担心排队的过程(因为锁的缘故,它们必须按顺序运行)需要很长时间才能完成。在锁定之前移动检查(!\u timer.Enabled)是否返回?如果_timer.Enabled=false被锁定,这可能无关紧要。不过我还没有想清楚。在锁之前和之后都有它可能会很好。(在定时器被禁用后,“之前”将停止任何排队,而“之后”将使已经排队的时间短路)@Terence:如果在锁之前添加检查,则在获得锁之后仍然需要添加检查。以这种方式添加两个检查将被调用,并有助于在出现多个并发线程的情况下减少争用,如您所述。但它也引入了创建竞争条件的可能性,因为您增加了代码的复杂性。如果您想保证在调用
Stop
返回后线程确实停止,您也不应该从
Stop
方法
\u timer.Enabled=false
中移除锁。放置
\u timer.Enabled=false
(这实际上表明处理程序的计时和持续时间有问题-您真的想耗尽线程池吗?)。但是,如果您还想使用
Start
方法来恢复计时器,避免由于性能原因而锁定会使启动->停止转换和处理类(必须实现
IDisposable
,因为
timer
IDisposable
)期间的事情复杂化。引用Jon Skeet的话:(如果)我必须在双重检查锁定和“每次锁定”代码之间进行选择,我会选择“每次锁定”,直到我得到真正的证据证明它导致了瓶颈。
 readonly object _lock = new object();

 void Stop()
 {
     lock (_lock)
     {
         _timer.Enabled = false; // equivalent to calling Stop()
     }
 }

 void Timer_Elapsed(...) 
 {
     lock (_lock)
     {
         if (!_timer.Enabled)
             return;

         // do stuff
     }
 }