System.Timers.Timer()由于聚合了经过的事件而多次触发

本文关键字:事件 经过 Timer Timers 于聚 System | 更新日期: 2023-09-27 18:05:06

我想让我的一段代码在被调用时启动一个计时器,并且我想让这个计时器一直运行直到我退出整个程序。我的问题是,每次我调用OnSomethingHappens(),经过的事件聚集(尽管我的努力-=)和计时器开始触发一个额外的时间(或至少这是我认为正在发生的)。我还尝试在类中定义定时器,但无济于事。下面是我代码的相关部分:

public override void OnSomethingHappens()
    {
        Timer aTimer= new System.Timers.Timer();
        aTimer.Elapsed -= (sender, e) => DoSomethingElse(sender, e);
        aTimer.Stop();
        aTimer.Close();
        aTimer.Elapsed += (sender, e) => DoSomethingElse(sender, e);
        aTimer.Interval = 1000;
        aTimer.AutoReset = true; // I want the timer to keep working, but only fire once each time
        Console.WriteLine("Enabling Timer aTimer");
        aTimer.Start();
}

我不能使用静态(不确定这有什么帮助,但我看到计时器被定义为静态在许多源),因为这个类有许多实例,我希望他们有单独的计时器。

谢谢。

System.Timers.Timer()由于聚合了经过的事件而多次触发

在没有AutoReset的情况下启动计时器,并在DoSomethingElse结束时重新启动。

aTimer.AutoReset = false;
aTimer.Start();
DoSomethingElse(..)
{
   // do stuff here
   aTimer.Start();
}

如果该类的每个实例都使用自己的计时器,则不需要静态。

    private Timer _aTimer;
    public void OnSomethingHappens()
    {  
        if (_aTimer != null)
        {    
            _aTimer.Enabled = true;  // start timer
            return;
        }
        _aTimer = new System.Timers.Timer();
        _aTimer.Elapsed += DoSomethingElse;
        _aTimer.Interval = 1000; // every 1 second
        _aTimer.Enabled = true;  // start timer
    }
    private void DoSomethingElse(object sender, ElapsedEventArgs e)
    {    
        _aTimer.Enabled = false; // stop timer
        // do w/e you want
    }

首先应该只创建一个计时器实例,并连接一个事件侦听器。在当前代码中,每次调用该方法时都会创建一个带有事件侦听器的新计时器。相反,将计时器作为一个类变量,并在构造函数中连接事件侦听器。

你可以在OnSomethingHappens中启动定时器,但是你想在对该方法的后续调用中发生什么?计时器应该重新启动,还是继续?

您可能还希望将类设置为IDisposable,或者至少提供一个Stop方法,以便在应用程序关闭时停止计时器。

public class MyClass : MyBaseClass, IDisposable
{
   private Timer _timer;
   private volatile bool _isStopped = true;
   public MyClass()
   {
       _timer = new Timer();
       _timer.Interval = 1000;
       _timer.Elapsed = OnTimerElapsed;
   }
   public void Stop()
   {
       _isStopped = true;
       _timer.Stop();
   }
   public void Dispose()
   {
      if (_timer != null)
      {
          Stop();
          _timer = null;
      }
   }
   protected override void OnSomethingHappens()
   {
       if (_timer.Enabled)
       {
          // Restart or do nothing if timer is already running?
       }
       else
       {
          _isStopped = false;
          _timer.Start();              
       }
   }
   private void OnTimerElapsed(object sender, EventArgs a)
   {
      if (_isStopped)
      {
          // If the Stop method was called after the Elapsed event was raised, don't start a long running operation
          return;
      }
   }
}