2013-05-15 40 views
3

我的工作基本上運行下面的代碼Windows服務:爲什麼在捕獲異常時調用Timer回調停止?

public class ServiceController 
{ 
    private FundsEngine _fundsEngine; 

    protected override void OnStart(string[] args) 
    { 
    var logsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs"); 
    if (Directory.Exists(logsPath) == false) 
    { 
     Directory.CreateDirectory(logsPath); 
    } 

    _fundsEngine = new FundsEngine(); 
    _fundsEngine.Start(); 
    } 
} 

該服務可以啓動「引擎」,它只是使用定時器來在指定的時間間隔執行代碼的類。

以下類是引擎的示例,該引擎使用System.Threading.Timer每5秒調用一次回調OnTick()

public class FundsEngine 
{ 
    private System.Threading.Timer _timer; 
    private static Logger _logger = LogManager.GetCurrentClassLogger(); 

    public void Start() 
    { 
    _logger.Trace("Begin Start"); 

    try 
    { 
     // details omitted 

     _timer = new Timer(OnTick); 
     _timer.Change(5000, Timeout.Infinite); 
    } 
    catch (Exception exception) 
    { 
     _logger.ErrorException("Error in Start.", exception); 
    } 
    finally 
    { 
     _logger.Trace("End Start"); 
    } 
    } 

    private void OnTick(object state) 
    { 
    _logger.Trace("Begin Tick"); 

    try 
    { 
     // do stuff 
     _timer.Change(5000, Timeout.Infinite); 
    } 
    catch (Exception exception) 
    { 
     _logger.ErrorException("Error in Tick. ", exception); 
    } 
    finally 
    { 
     _logger.Trace("End Tick"); 
    } 
    } 
} 

如下面在日誌中所示,按預期工作的定時器,調用OnTick()方法每5秒。

2013-05-14 16:27:01.2261|TRACE|Begin Start 
2013-05-14 16:27:03.8514|TRACE|End Start 
2013-05-14 16:27:08.8569|TRACE|Begin Tick 
2013-05-14 16:27:08.8709|TRACE|End Tick 
2013-05-14 16:27:13.8734|TRACE|Begin Tick 
2013-05-14 16:27:13.8734|TRACE|End Tick 
2013-05-14 16:27:18.8809|TRACE|Begin Tick 
2013-05-14 16:27:18.8809|TRACE|End Tick 
2013-05-14 16:27:23.8894|TRACE|Begin Tick 
2013-05-14 16:27:23.8894|TRACE|End Tick 
2013-05-14 16:27:28.8969|TRACE|Begin Tick 
2013-05-14 16:27:28.8969|TRACE|End Tick 
2013-05-14 16:27:33.9044|TRACE|Begin Tick 
2013-05-14 16:27:33.9044|TRACE|End Tick 

如果有例外是夾在OnTick()方法的情況下,我的期望是,它會被記錄下來,並且該服務將繼續運行,使得OnTick()方法將在5秒內再次調用。但是,情況並非如此,因爲在處理異常之後從不再調用回調。爲什麼是這樣?

2013-05-14 16:29:03.8574|TRACE|Begin Start 
2013-05-14 16:29:03.8574|TRACE|End Start 
2013-05-14 16:29:08.8709|TRACE|Begin Tick 
2013-05-14 16:29:09.9750|ERROR|Error in Tick. System.Net.Sockets.SocketException (0x80004005): No connection could be made because the target machine actively refused it 127.0.0.1:22 
2013-05-14 16:29:09.9750|TRACE|End Tick 

回答

1
_timer.Change(5000, Timeout.Infinite); 

你沒有創建一個週期定時器,傳遞無限的期間說法。計時器只會調用OnTick()一次。然而,代碼非常不完整,它可以工作的唯一方法是再次調用Change()來爲計時器充電。

這個Change()調用被異常繞過的機率很高。如果你想保留它,那麼這個Change()調用屬於最後的塊。儘管這樣做並不是一個好主意,但進程狀態已損壞並且只會再次崩潰的非零機率。一遍又一遍。你至少應該採取對策,並且還要計算連續崩潰的次數,放棄反覆爆炸。

+0

糾正所有點。我編輯了我的原始帖子以顯示缺失的細節。不知道我是如何錯過的,但它顯然是完美的。 –

1

this StackOverflow後國家接受的答案,在例外的情況下...

System.Threading.Timer將終止程序。

我相信是你所看到的。

+0

我看到這個,但認爲它只是指未處理的異常,如[這裏](http://stackoverflow.com/a/1718610/213159)所述,但一直未能找到澄清。 –

+0

因此,除了在try catch塊中使用整個調用的函數之外,我們無法處理它們嗎? – MonsterMMORPG

相關問題