停止时同步 Timers.Timer elapsed 方法 [英] Synchronizing a Timers.Timer elapsed method when stopping

查看:22
本文介绍了停止时同步 Timers.Timer elapsed 方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

参考 MSDN 关于 System.Timers.Timer:

With reference to this quote from MSDN about the System.Timers.Timer:

Timer.Elapsed 事件在ThreadPool 线程,所以事件处理方法可能在一个上运行线程同时调用Timer.Stop 方法在另一个上运行线.这可能会导致在调用停止方法.这场比赛条件不能简单地预防通过比较 SignalTime 属性随着 Stop 方法的时间调用,因为事件处理方法可能已经在执行调用 Stop 方法,或者可能瞬间开始执行当调用 Stop 方法并且保存停止时间的时刻.如果防止线程是至关重要的调用 Stop 方法在事件处理过程中进行方法仍在执行,使用更多强大的同步机制,例如作为 Monitor 类或比较交换方法.使用的代码CompareExchange 方法可以是在示例中找到Timer.Stop 方法.

The Timer.Elapsed event is raised on a ThreadPool thread, so the event-handling method might run on one thread at the same time that a call to the Timer.Stop method runs on another thread. This might result in the Elapsed event being raised after the Stop method is called. This race condition cannot be prevented simply by comparing the SignalTime property with the time when the Stop method is called, because the event-handling method might already be executing when the Stop method is called, or might begin executing between the moment when the Stop method is called and the moment when the stop time is saved. If it is critical to prevent the thread that calls the Stop method from proceeding while the event-handling method is still executing, use a more robust synchronization mechanism such as the Monitor class or the CompareExchange method. Code that uses the CompareExchange method can be found in the example for the Timer.Stop method.

谁能举一个强大的同步机制,例如 Monitor 类"的例子来解释这究竟意味着什么?

Can anyone give an example of a "robust synchronization mechanism such as the Monitor class" to explain what this means exactly?

我认为这意味着以某种方式使用锁,但我不确定您将如何实现它.

I am thinking it means use a lock somehow, but I am unsure how you would implement that.

推荐答案

可靠地停止 System.Timers.Timer 确实是一项重大工作.最严重的问题是,由于线程池调度程序算法,它用来调用 Elapsed 事件的线程池线程可以备份.有几个备用电话并不罕见,有数百个在技术上是可能的.

Stopping a System.Timers.Timer reliably is indeed a major effort. The most serious problem is that the threadpool threads that it uses to call the Elapsed event can back up due to the threadpool scheduler algorithm. Having a couple of backed-up calls isn't unusual, having hundreds is technically possible.

您将需要两个同步,一个确保仅在没有 Elapsed 事件处理程序运行时停止计时器,另一个确保这些备份的 TP 线程不会造成任何伤害.像这样:

You'll need two synchronizations, one to ensure you stop the timer only when no Elapsed event handler is running, another to ensure that these backed-up TP threads don't do any harm. Like this:

    System.Timers.Timer timer = new System.Timers.Timer();
    object locker = new object();
    ManualResetEvent timerDead = new ManualResetEvent(false);

    private void Timer_Elapsed(object sender, ElapsedEventArgs e) {
        lock (locker) {
            if (timerDead.WaitOne(0)) return;
            // etc...
        }
    }

    private void StopTimer() {
        lock (locker) {
            timerDead.Set();
            timer.Stop();
        }
    }

考虑将 AutoReset 属性设置为 false.另一种方式很脆弱,Elapsed 事件是从捕获异常的内部 .NET 方法调用的.非常讨厌,您的计时器代码在没有任何诊断的情况下停止运行.我不知道历史,但肯定有另一个 MSFT 团队对这个烂摊子大发雷霆,写了 System.Threading.Timer.强烈推荐.

Consider setting the AutoReset property to false. That's brittle another way, the Elapsed event gets called from an internal .NET method that catches Exception. Very nasty, your timer code stops running without any diagnostic at all. I don't know the history, but there must have been another team at MSFT that huffed and puffed at this mess and wrote System.Threading.Timer. Highly recommended.

这篇关于停止时同步 Timers.Timer elapsed 方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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