問題 在一個 Timer 時鐘的周期方法內,有一個 迴圈,當執行到某些特定的語句時,會從頭開始執行,而不會執行後續的語句。 分析 該問題我在初步分析之後,發現可能是由於程式出現了異常,但是被吞噬掉造成的。在我某一個 item 元素當中,其值為 應該會拋出空異常。但是沒有異常拋出,後續我不知道哪個地方 ...
問題
在一個 Timer 時鐘的周期方法內,有一個 foreach
迴圈,當執行到某些特定的語句時,會從頭開始執行,而不會執行後續的語句。
分析
該問題我在初步分析之後,發現可能是由於程式出現了異常,但是被吞噬掉造成的。在我某一個 item 元素當中,其值為 null
應該會拋出空異常。但是沒有異常拋出,後續我不知道哪個地方吞噬了異常,就在迴圈體內增加了一個 if
語句過濾掉了 null
元素。
不過之後仍然會出現最開始所說的問題,看來還有其他的地方在拋出異常,最後排查到是執行 DevExpress 圖表控制項的 BeginDataUpdate()
和 EndDataUpdate()
之後就會出現上述癥狀。
查閱了我的 Timer
是參照 ABP 實現的一個 Timer
,找到調用回調方法的地方,發現是我自己將異常捕獲並將其忽略掉了。
private void TimerCallBack(object state)
{
lock (_taskTimer)
{
if (!_running || _performingTasks)
{
return;
}
_taskTimer.Change(Timeout.Infinite, Timeout.Infinite);
_performingTasks = true;
}
try
{
Elapsed?.Invoke(this, new EventArgs());
}
catch
{
// ignored
}
finally
{
lock (_taskTimer)
{
_performingTasks = false;
if (_running)
{
_taskTimer.Change(Period, Timeout.Infinite);
}
Monitor.Pulse(_taskTimer);
}
}
}
根據上圖來看,確實是我回調方法中的代碼拋出了異常,導致後臺任務重新執行。
解決
將跨線程訪問語句修複之後,程式運行正常,後面我也在 catch 語句塊裡面增加了異常日誌寫入,成功解決問題。