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

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

问题描述

参考 MSDN 关于 System.Timers.Timer:

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

Timer.Elapsed 事件是在ThreadPool 线程,所以事件处理方法可能运行在一个线程同时调用Timer.Stop 方法在另一个上运行线.这可能会导致Elapsed 事件在停止方法被调用.这场比赛不能简单地防止这种情况通过比较 SignalTime 属性随着停止方法的时间调用,因为事件处理方法可能已经在执行时停止方法被调用,或者可能开始执行当 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 已用方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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