【问题标题】:How to fire timer.Elapsed event immediately如何立即触发 timer.Elapsed 事件
【发布时间】:2011-08-03 09:08:00
【问题描述】:

我正在使用System.Timers.Timer 类创建一个带有Timer.Elapsed 事件的计时器。问题是 Timer.Elapsed 事件只有在间隔时间过去后才会第一次触发。

有没有办法在启动计时器后立即引发Timer.Elapsed 事件?

我在 System.Timers.Timer 类中找不到任何相关属性。

【问题讨论】:

  • 你能提供一点代码吗?也许在设置计时器后调用事件处理程序可以解决问题

标签: c# events timer


【解决方案1】:

只需自己调用Timer_Tick 方法即可。


如果您不想处理 Tick 回调方法的参数,则只需将 Timer_Tick 中的代码放入另一个方法中,然后从 Timer_Tick 和 Timer.Start() 调用之后调用它


正如@Yahia 所指出的,您还可以使用System.Threading.Timer 计时器,您可以将其设置为初始延迟为0。但请注意,回调将在不同的线程上运行,如与在 UI 线程上运行的 Windows.Forms.Timer 上的回调相反。因此,如果您使用 System.Threading.Timer 更新任何 UI 控件(未正确调用),它将崩溃。

【讨论】:

  • 对我来说似乎是解决方案。但是如果我想处理 Tick 回调方法的参数,我应该使用什么? OnTimer(Object source, ElapsedEventArgs e)source 我的计时器实例?如何创建一个新的ElapsedEventArgs
  • System.Windows.Forms.TimerTick 事件有一个sourceEventArgs 参数,源是计时器,只需为第二个参数执行new EventArgs()。如果您使用的是System.Threading.Timer,那么对于第二个参数,只需创建一个新的 ElapsedEventArgs,将 SignalTime 设置为 DateTime.Now() 之类的东西。
  • OnTimer(timerInstance, new ElapsedEventArgs() { ... }); 根据需要填写 ElapsedEventArgs 字段。
  • @Matten 实际上我不能 - ElapsedEventArgs 没有定义构造函数。我错过了一点吗?
  • @Leito 是的,ElapsedEventArgs 的 ctor 被标记为内部。所以使用null 作为第二个参数,在处理程序代码中if(e==null) signalTime=DateTime.Now 将产生与使用signalTime=DateTime.Now 初始化ElapsedEventArgs 相同的结果(这是不可能的)
【解决方案2】:

我刚刚用空参数调用了**ElapsedEventHandler**

【讨论】:

    【解决方案3】:

    我知道这个答案很晚,但是如果您希望在 100 毫秒(默认间隔)内触发您的 System.Timers.Timer,那么您可以简单地初始化 Timer 对象而不指定时间间隔,然后在被调用函数中设置时间间隔随心所欲。这是我在 Windows 服务中使用的示例:

    private static Timer _timer;
    
    protected override void OnStart(string[] args)
    {
        _timer = new Timer(); //This will set the default interval
        _timer.AutoReset = false;
        _timer.Elapsed = OnTimer;
        _timer.Start();
    }
    
    private void OnTimer(object sender, ElapsedEventArgs args)
    {
        //Do some work here
        _timer.Stop();
        _timer.Interval = 50000; //Set your new interval here
        _timer.Start();
    }
    

    【讨论】:

    • 最佳答案!尽管您甚至不需要 _timer.Stop(); bc 您设置了 _timer.AutoReset = false;,所以您输入 OnTimer 并将 _timer.Enabled 设置为 false 无论如何。但它也不会造成任何伤害。
    【解决方案4】:

    不确定System.Timers.Timer,但请尝试

    System.Threading.Timer T = new System.Threading.Timer(new TimerCallback(DoSomething), null, 0, 30000);
    

    这会立即开始(第一次运行 0 毫秒,后续运行 30000 毫秒)...


    http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx
    http://msdn.microsoft.com/en-us/library/2x96zfy7.aspx

    【讨论】:

    • 我应该指定我不想使用System.Threading.Timers,因为我开发了一个 Windows 服务。无论如何谢谢:)
    • 我们在 Windows 服务中使用 System.Threading.Timers - 它们是不允许的,或者在 Windows 服务中可能会出现什么样的问题?
    • 写在msdn: System.Threading.Timer 是一个简单的轻量级定时器,它使用回调方法,由线程池线程提供服务。不建议与 Windows 窗体一起使用,因为它的回调不会发生在用户界面线程上。 System.Windows.Forms.Timer 是与 Windows 窗体一起使用的更好选择。对于基于服务器的计时器功能,您可以考虑使用 System.Timers.Timer,它会引发事件并具有附加功能。
    • 谢谢 :-) 这也是我读到的......所以没有什么禁止在 Windows 服务中使用,只是有另一个选项具有更多功能。
    • 总是偏爱 System.Threading.Timer 而不是 System.Timers.Timer,它是一个更好的计时器类。
    【解决方案5】:
    Task.Run(() =>
    {
       Timer_Elapsed(null, null);
    });
    

    创建/配置计时器后,对我来说工作正常...

    【讨论】:

    • 为什么这被否决了?这将起作用并通过一个工作示例回答问题。
    【解决方案6】:

    如果您希望能够随时触发事件(不仅仅是在您启动计时器的那一刻),您可以在您自己的 MyTimer 类中封装一个计时器。此类公开了原始的 Timer 方法和属性。此外,我添加了一个带有显式添加和删除的事件。通过这种方式,每当您向事件添加委托时,它都会添加到私有 MyTimer 的事件和原始计时器 Elapsed 事件中。这意味着计时器以通常的方式触发 Elapsed,但您可以手动触发调用 RaiseElapsed 的事件(这听起来应该更简单查看代码)。

    public class MyTimer
    {
        Timer t = new Timer();
        event ElapsedEventHandler timerElapsed;
    
        public event ElapsedEventHandler Elapsed
        {
            add
            {
                t.Elapsed += value;
                timerElapsed += value;
            }
            remove
            {
                t.Elapsed -= value;
                timerElapsed -= value;
            }
        }
    
        public double Interval
        {
            get
            {
                return t.Interval;
            }
            set
            {
                t.Interval = value;
            }
        }
    
        public void Start()
        {
            t.Start();
        }
    
        public void Stop()
        {
            t.Stop();
        }
    
        public void RaiseElapsed()
        {
            if (timerElapsed != null)
                timerElapsed(null, null);
        }
    }
    

    【讨论】:

      【解决方案7】:

      第一次,计时器将在 1 秒后启动。之后,它的间隔将更改为每 30 秒或其他任何时间......

          //main function    
          Timer timer = new Timer(1000);   //initial start after 1 second
              timer.Elapsed += new ElapsedEventHandler(TimerElapsedMethod);
              timer.Start();            
          }
          private void TimerElapsedMethod(object sender, ElapsedEventArgs e) 
          {
              Timer timer = (Timer)sender; // Get the timer that fired the event
              timer.Interval = 30000;      // Change the interval to whatever
              .
              .
              .
          }
      

      【讨论】:

        【解决方案8】:

        我已经用 AddHandler 在 VB.NET 中实现了

        Public Class clsMain Inherits ServiceBase
        
        Protected Overrides Sub OnStart(ByVal args() As String)
        ' Add code here to start your service. This method should set things
        ' in motion so your service can do its work.
        gTimer.Interval = 1000  
        gTimer.Enabled = True
        AddHandler gTimer.Elapsed, AddressOf gTimer_Elapsed
        End Sub
        
        'When the timer is elapsed this event will be fired
        
        Protected Sub gtimer_Elapsed(ByVal source As Object, ByVal e As ElapsedEventArgs)
        'Stop the timer and do some work
        gTimer.Stop()
        'Custom code
        'Here
        'Start to raise the elapsed event again
        gTimer.Start()
        End Sub
        End Class
        

        【讨论】:

          【解决方案9】:

          我不是专业人士,因此请加少许盐,但它确实有效。我创建了一个函数,而不是将代码放入计时器子中,而是将其放入函数中。然后我只是在需要时调用该函数(在我的情况下是在页面加载时),然后计时器代码将在间隔时间触发并简单地在计时器子代码中调用该函数。

          【讨论】:

            【解决方案10】:

            这是简单的答案。 (假设您使用的是 Windows 窗体)

            将计时器控件拖到窗体后,将 enabled 属性设置为 true,并将 Interval 属性设置为您希望的初始值。 (默认为 100,会立即启动 tick 事件)

            然后在您的滴答事件中,只需检查 Interval 属性的值。如果它不是您想要的值,请设置它。 就这么简单。如果动态创建计时器,则可以在 C# 代码中完成相同的操作。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-06-18
              • 2013-11-07
              • 1970-01-01
              • 2020-03-29
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多