假设我们将此事件附加到timer事件处理程序。
private void TimerTick(object sender, ElapsedEventArgs e)
{
    if(_gaurd) return;
    lock (this) // lock per instance
    {
        _gaurd = true;
        if (!_timer.Enabled) return;
        OnTick(); // somewhere inside here timer may pause it self.
        _gaurd = false;
    }
}现在有两件事可以暂停这个定时器。一个是来自UI线程的用户请求,第二个是定时器,它可能会暂停它自己。
如果定时器暂停它自,我们可以保证暂停将在我们继续之前完成。
timer.Stop();
OnPause(); // timer must be paused because OnPause() is not thread safe.但是如果用户请求定时器暂停,请求是来自另一个线程和,我们不能保证计时器是否完全暂停。
timer.Stop();
OnPause(); // timer event may be still inside OnTick() and may conflict with OnPause()因此,我正在寻找一种方法,使这个线程安全的。到目前为止,这是我尝试过的,但我不确定这在所有情况下是否有效。
它看起来很好,但想确保如果有什么我不知道的。或者可能知道是否有更好的方法来确保进程线程的安全。
我试图将用户请求从计时器的内部工作中分离出来。因此,对于我的计时器,我有两个暂停方法。
public class Timer
{
    internal void InternalStop() // must be called by timer itself.
    {
        timer.Pause(); // causes no problem
    }
    public void Stop() // user request must come here. (if timer call this deadlock happens)
    {
        InternalStop();
        lock (this) // reference of timer
        {
            // do nothing and wait for OnTick().
        }
    }
}这不是实际的代码,但行为是相同的。它应该说明这个类不是线程安全的。:
public class WorkingArea
{
    private List<Worker> _workers;
    public void OnTick()
    {
        foreach(var worker in _workers)
        {
            worker.Start();
        }
        if(_workers.TrueForAll(w => w.Ends))
        {
            PauseTimer();
        }
    }
    public void OnPause() // after timer paused
    {
        foreach(var Worker in _workers)
        {
            worker.Stop();
        }
    }
}发布于 2016-12-18 17:47:00
我的计时器已经安全了。
这都是因为我不知道Re-entrant locks
因此,如果用户从另一个线程请求暂停计时器,lock将很好地工作,并将阻塞,直到计时器完全暂停。
如果定时器内部暂停它自己,它将不会处理锁定。因为它位于同一个线程中,所以获得了锁。
public class Timer
{
    private timer = new System.Timers.Timer();
    private bool _guard = false;
    // stops the timer and waits until OnTick returns and lock releases.
    // timer can safely pause it self within OnTick.
    // if user request to pause from another thread, full pause is ensured
    public void Stop()       
    {
        timer.Pause();
        lock (this) // reference of timer. it wont dead lock
        {
            // do nothing and wait for OnTick().
        }
    }
    private void TimerTick(object sender, ElapsedEventArgs e)
    {
        if(_gaurd) return;
        lock (this) // lock per instance
        {
            _gaurd = true;
            if (!_timer.Enabled) return;
            OnTick(); // somewhere inside here timer may pause it self.
            _gaurd = false;
        }
    }
}https://stackoverflow.com/questions/41029893
复制相似问题