異常吞噬問題一則

問題

在一個 Timer 時鐘的週期方法內,有一個 foreach 循環,當執行到某些特定的語句時,會從頭開始執行,而不會執行後續的語句。this

分析

該問題我在初步分析以後,發現多是因爲程序出現了異常,可是被吞噬掉形成的。在我某一個 item 元素當中,其值爲 null 應該會拋出空異常。可是沒有異常拋出,後續我不知道哪一個地方吞噬了異常,就在循環體內增長了一個 if 語句過濾掉了 null 元素。線程

不過以後仍然會出現最開始所說的問題,看來還有其餘的地方在拋出異常,最後排查到是執行 DevExpress 圖表控件的 BeginDataUpdate()EndDataUpdate() 以後就會出現上述症狀。3d

查閱了個人 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);
        }
    }
}

根據上圖來看,確實是我回調方法中的代碼拋出了異常,致使後臺任務從新執行。code

解決

將跨線程訪問語句修復以後,程序運行正常,後面我也在 catch 語句塊裏面增長了異常日誌寫入,成功解決問題。orm

相關文章
相關標籤/搜索