簡體   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