C#Timer on Elapsed Time不调用方法

时间:2013-09-13 12:28:18

标签: c# .net multithreading .net-4.0 timer

以下课程来自.Net Windows服务。方法 DoSomeDatabaseStuff 在第一次启动时需要10分钟,但是当时间结束时,此方法不会再次被调用。

public class Test
{
        public void Start()
        {
            DoSomeDatabaseStuff();

            _oTimer = new Timer(60000);
            _oTimer.Elapsed += OnTimeout;
            _oTimer.AutoReset = true;
            _oTimer.Start();
        }

        private void OnTimeout(object source, ElapsedEventArgs e)
        {
            DoSomeDatabaseStuff();

            _oTimer = new Timer(60000);
            _oTimer.Elapsed += OnTimeout;
            _oTimer.AutoReset = true;
            _oTimer.Start();
        }
}

4 个答案:

答案 0 :(得分:6)

此代码中存在许多严重问题:

  • 如果Start方法是服务的OnStart()方法,那么您永远无法启动服务。 OnStart()必须在30秒内完成。只是初始化计时器而不做任何其他事情
  • 在Elapsed事件处理程序中创建另一个Timer是一个严重的错误。您的事件处理程序现在将运行两次。在第二次调用之后,它将运行三次。等等。
  • 您的测试程序不会测试代码在服务中的运行方式。 Elapsed事件处理程序将永远不会运行,因为测试将在您的事件处理程序运行之前完成。这解释了你的观察
  • 必须在Elapsed事件处理程序中使用try / catch。如果不这样做,那么在没有诊断的情况下将吞下任何异常。 System.Timers.Timer类很讨厌,喜欢System.Threading.Timer而不是解释你的观察
  • 必须确保您的事件处理程序是可重入的。它可以在前一次调用事件处理程序仍然繁忙时再次运行,这将在任务超过一分钟时发生。这很少有好结果。设置AutoReset = false是一种避免这种重入的简单方法,在事件处理程序结束时启动计时器备份以使其重复。

答案 1 :(得分:3)

我在windows-services中使用System.Threading.Timer

也许这也解决了您的问题,因为其他人在Windows服务中System.Timers.Timer也存在问题:"我发现System.Timers.Timer只是没有&# 39;在我的Windows服务应用程序中工作。因此,我已切换到System.Threading.Timer"

请参阅:Windows Service System.Timers.Timer not firing

private void InitService()
{
    //starts immediately, interval is in TimeSpan 
    this._oTimer = new System.Threading.Timer(
        OnTimeout,
        null, 
        TimeSpan.Zero,
        TimeSpan.FromMinutes(10)
    );
}

protected override void OnStart(string[] args)
{
    InitService();
}

protected override void OnStop()
{
    this._oTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
}

private void ImportTimer_Elapsed(Object state)
{
    DoSomeDatabaseStuff();
}

答案 2 :(得分:2)

您的程序在计时器运行之前结束。 Timer工作static void Main(string[] args) { Test t = new Test(); t.Start(); Console.ReadLine(); } 当主线程停止时,会终止。

尝试

{{1}}

答案 3 :(得分:1)

不是每次都创建一个新的计时器,而是尝试将OnTimeout处理程序设置为:

_oTimer.Stop();
DoSomeDatabaseStuff();
_oTimer.Start();

与方法Start()类似。