当Enabled设置为false时,为什么System.Timer.Timer仍会触发事件? [英] Why does System.Timer.Timer still fire events when Enabled is set to false?

查看:55
本文介绍了当Enabled设置为false时,为什么System.Timer.Timer仍会触发事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have attempted to create a derived class of Timer that allows for a 'Pause' latch to be set to keep the worker thread from reactivating the timer. However, Elapsed events are continued to be raised when AutoReset is set to false and the Enabled accessor appears to be doing it's job in preventing the Enabled property of the base class from being modified once the Paused variable is set.

为什么会发生这种情况,或者我应该使用什么策略来进一步了解此处实际上发生了什么互动?

Why is this happening or what strategies should I use to further understand what interactions are actually happening here?

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

I have attached the implementation of the derived class below.

    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;
          }
        }
      }
    }

说明问题的示例.

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;
    }
}

推荐答案

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

注意如果Enabled和AutoReset都设置为false,并且以前已启用计时器,则设置Interval属性将导致引发Elapsed事件一次,就像Enabled属性已设置为true一样.要在不引发事件的情况下设置时间间隔,可以将AutoReset属性临时设置为true.

Note If Enabled and AutoReset are both set to false, and the timer has previously been enabled, setting the Interval property causes the Elapsed event to be raised once, as if the Enabled property had been set to true. To set the interval without raising the event, you can temporarily set the AutoReset property to true.

建议的将 AutoReset 设置为true的解决方案不能解决问题,因为在事件处理程序中也存在将未记录的将 AutoReset 设置为true的行为,该事件处理程序还允许发生事件被解雇.

The recommended solution of setting AutoReset to true does not solve the problem because there is an undocumented behavior of setting AutoReset to true during an event handler also allowing for an event to be fired.

解决方案似乎是将派生对象构建到某种程度,以便您可以阻止发生事件的任何明显方式都可以发生.

The solution seems to be to build out the derived object to the point where you can keep any of the apparently many ways that an event can be fired again from happening.

下面是我最后的实现.

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){}
}

这篇关于当Enabled设置为false时,为什么System.Timer.Timer仍会触发事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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