繁体   English   中英

C#Timer on Elapsed Time不调用方法

[英]C# Timer on Elapsed Time does not call method

以下类来自.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();
        }
}

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

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

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

也许这也解决了你的问题,因为其他人也在Windows服务中的System.Timers.Timer问题: “我发现System.Timers.Timer在我的Windows服务应用程序中不起作用。所以我' ve切换到System.Threading.Timer

请参阅: Windows Service System.Timers.Timer未触发

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

您的程序在计时器运行之前结束。 Timer正在后台线程中工作当主线程停止时终止。

尝试

static void Main(string[] args)
{
    Test t = new Test();
    t.Start();
    Console.ReadLine();
}

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

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

与方法Start()类似。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM