当Enabled设置为false时,为什么System.Timer.Timer仍会触发事件?

Eri*_*ick 7 c# timer

我试图创建一个派生类Timer,它允许设置一个'Pause'锁存器,以防止工作线程重新激活定时器.但是,当AutoReset设置为false时,继续引发Elapsed事件,并且Enabled访问器似乎正在执行它的工作,以防止在设置Paused变量后修改基类的Enabled属性.

为什么会发生这种情况或我应该使用什么策略来进一步了解这里实际发生的交互?

我已经附加了下面的派生类的实现.

    using System.Timers
    class PauseableTimer : Timer
    {
      public bool Paused;
      new public bool Enabled
      { 
        get
        {
          return base.Enabled;
        } 
        set
        {
          if (Paused)
          {
            if (!value) base.Enabled = false;
          } 
          else
          {
            base.Enabled = value;
          }
        }
      }
    }
Run Code Online (Sandbox Code Playgroud)

说明问题的例子.

class Program
{
    private static PauseableTimer _pauseableTimer;
    private static int _elapsedCount;
    static void Main(string[] args)
    {
        _pauseableTimer = new PauseableTimer(){AutoReset = false,Enabled = false,Paused = false};

        _pauseableTimer.Elapsed += pauseableTimer_Elapsed;
        _pauseableTimer.Interval = 1;
        _pauseableTimer.Enabled = true;
        while(_elapsedCount<100)
        {
            if (_elapsedCount > 50) _pauseableTimer.Paused = true;
        }
    }

    static void pauseableTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        Console.WriteLine(String.Format("this.Enabled:'{0}',Paused:'{1}',AutoReset:'{2}",_pauseableTimer.Enabled,_pauseableTimer.Paused,_pauseableTimer.AutoReset));
        _elapsedCount++;
        _pauseableTimer.Interval = _pauseableTimer.Interval == 1 ? 2 : 1; //This line breaks it.
        _pauseableTimer.Enabled = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ick 7

相关文档,System.Timers.Timer.Interval

注意如果Enabled和AutoReset都设置为false,并且先前已启用计时器,则设置Interval属性会导致Elapsed事件被提升一次,就像Enabled属性已设置为true一样.若要设置间隔而不引发事件,可以暂时将AutoReset属性设置为true.

建议设置AutoReset为true的解决方案无法解决问题,因为AutoReset在事件处理程序中还存在未记录的设置为true的行为,同时允许触发事件.

解决方案似乎是将派生对象构建到可以保持事件可以再次发生的任何显然方式的任何方面.

以下是我结束的实现.

public class PauseableTimer : Timer
{
    private bool _paused;
    public bool Paused
    {
        get { return _paused; }
        set 
        { 
            Interval = _interval;
            _paused = value;
        }
    }

    new public bool Enabled
    {
        get
        {
            return base.Enabled;
        }
        set
        {
            if (Paused)
            {
                if (!value) base.Enabled = false;
            }
            else
            {
                base.Enabled = value;
            }
        }
    }

    private double _interval;
    new public double Interval
    {
        get { return base.Interval; }
        set
        {
            _interval = value;
            if (Paused){return;}
            if (value>0){base.Interval = _interval;}
        }
    }

    public PauseableTimer():base(1){}

    public PauseableTimer(double interval):base(interval){}
}
Run Code Online (Sandbox Code Playgroud)