首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

.NET 即時監控線程掛起與死循環:心跳機制與堆疊追蹤實作

     編輯:關於.NET

問題背景

.NET 程式除錯較 C/C++ 容易,但仍難以應對:

  1. 線程不明原因掛起(如死鎖)
  2. 程式進入死循環佔滿 CPU

本文實作一個 ThreadMonitor 類別,以獨立高優先權監控線程,即時偵測並報告上述異常。

核心架構

public class ThreadMonitor
{
    private Thread _monitorThread;
    private Dictionary<int, TCB> _tcbTable = new Dictionary<int, TCB>();
    private object _registerLock = new object();

    public ThreadMonitor()
    {
        _monitorThread = new Thread(MonitorTask) { Priority = ThreadPriority.Highest, IsBackground = true };
    }

    public void Start() => _monitorThread.Start();

    public void Register(MonitorParameter mp)
    {
        lock (_registerLock)
            _tcbTable[mp.Thread.ManagedThreadId] = new TCB(mp);
    }

    public void Heartbeat(Thread t)
    {
        var tcb = GetTCB(t);
        tcb.LastHeartbeat = DateTime.Now;
        tcb.HitTimes = 0;
        tcb.Status &= ~ThreadStatus.Hang;
    }
    // ... 監控邏輯詳見下文
}

線程掛起偵測:心跳機制

  • 被監控線程需定時呼叫 Heartbeat()(如每秒一次)。
  • 監控線程定期檢查 LastHeartbeat,超過 HangTimeout 視為掛起。
  • 掛起時透過 Thread.Suspend() 暫停目標線程,取得 StackTrace,再 Resume() 恢復。
private string GetThreadStackTrace(Thread t)
{
    t.Suspend();
    var stack = new StackTrace(t, true);
    t.Resume();
    return stack.ToString();
}

注意: Suspend/Resume 已被標記過時,但此處僅用於瞬間取得堆疊,風險可控。

死循環偵測:CPU 佔用率 + 命中率雙重判斷

  1. 定時讀取 Process.TotalProcessorTime 計算進程 CPU 使用率。
  2. 若持續超過 90% * (100 / 核心數),判定進程疑似死循環。
  3. 進一步每秒採樣各線程狀態,若某線程連續處於 Running 且無心跳,鎖定為死循環源頭。
  4. 若有心跳但 CPU 高,仍列為可疑並記錄堆疊供人工判斷。

實測報告範例

主線程 Sleep 20 秒模擬掛起

ThreadMonitorEvent
Thread Name: Main thread
Thread Status: Hang
Thread Stack:
   at System.Threading.Thread.SleepInternal(Int32 millisecondsTimeout)
   at DotNetDebug.Form1.buttonHang_Click(Object sender, EventArgs e)
   ...

計數器線程 while(true){} 死循環

ThreadMonitorEvent
Thread Name: Counter thread
Thread Status: Hang, DeadCycle
Thread Stack:
   at DotNetDebug.Form1.DoDeadCycle()
   at DotNetDebug.Form1.Counter()
   ...

完整測試程式碼結構

  • WinForm 主線程 + 計數器背景線程
  • Timer 每秒送心跳給主線程
  • 按鈕觸發 Thread.Sleep(20000) 或 _DeadCycle = true
  • 異常寫入 Report.log

原始碼下載

點此下載完整專案原始碼

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved