| 工具 | 關注指標 | 閾值 |
| 任務管理器 → 詳細信息 → 選列 | GDI Objects, USER Objects, Handles | GDI > 5,000 警惕,> 9,000 必崩 |
| PerfMon (性能監視器) | Process → Private Bytes, Virtual Bytes, Gen 2 GC Count | Private Bytes 持續上升不回落 = 洩漏 |
| Visual Studio 診斷工具 / dotMemory | 托管堆 / 非托管堆 / 最終化佇列 | 最終化佇列堆積 = Dispose 未調用 |
| WinDbg + SOS | `!gchandles`, `!objsize`, `!address -summary` | 定位具體類型洩漏 |
解決方案 (按優先級)
1. 實現 `IDisposable` 模式,嚴格釋放非托管資源
public sealed class VideoPanel : UserControl, IDisposable {
private IntPtr _playHandle = IntPtr.Zero; // 廠商 SDK 播放句柄
private bool _disposed;
public void LoadCamera(string ip, int port, string user, string pwd) {
Stop(); // 先清理舊資源
_playHandle = SDK_StartPlay(ip, port, user, pwd, this.Handle);
}
public void Stop() {
if (_playHandle != IntPtr.Zero) {
SDK_StopPlay(_playHandle);
_playHandle = IntPtr.Zero;
}
// 釋放 GDI: 這裡釋放可能創建的 Bitmap/DC
}
// 標準 Dispose 模式
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing) {
if (!_disposed) {
Stop();
if (disposing) {
// 釋放托管資源: 事件取消訂閱、子控件 Dispose
}
_disposed = true;
}
}
~VideoPanel() => Dispose(false);
}
2. Timer 觸發時「先停舊、再啟新」,避免並發播放
private void Timer_Tick(object sender, EventArgs e) {
foreach (var panel in _panels) panel.Stop(); // 統一停止
// 切換邏輯:更新 IP 列表索引
foreach (var panel in _panels) panel.LoadCamera(nextIp[panel.Index]);
}
3. 降低輪詢頻率 / 改用事件驅動
- 若 SDK 支援回調 (`SetRealDataCallBack`),**不要用 Timer 輪詢**,改用回調推幀
- 最小間隔建議 **≥ 5 分鐘**,且單次切換耗時 < 10 秒
4. 硬體加速與解碼優化
- 啟用 SDK 硬解 (`SDK_EnableHardwareDecode`)
- 降低碼流:主碼流 → 子碼流 (CIF/D1),減少解碼壓力 60%+
- 關閉不必要的疊加 (OSD、十字線、時間戳)
5. 記憶體限制與自動重啟 (最後防線)
// App.config
// 監控記憶體,超閾值重啟進程
private void CheckMemory() {
var pm = Process.GetCurrentProcess();
if (pm.PrivateMemorySize64 > 1.5L * 1024 * 1024 * 1024) { // 1.5 GB
Log("Memory pressure, restarting...");
Process.Start(Application.ExecutablePath);
Environment.Exit(0);
}
}
總結
**「內存不足」實為非托管資源 (GDI/Handle/原生 SDK) 洩漏**。**核心對策:`IDisposable` 嚴格釋放 + Timer 串行化切換 + 子碼流降碼 + 硬解啟用**。配合 PerfMon/WinDbg 定位具體洩漏類型,針對性修復廠商 SDK 調用代碼。
- 上一篇文章: Java「Cannot inherit from final class」類衝突排查:HttpClient 4.x 多版本 Jar 包導致驗證錯誤
- 下一篇文章: MFC ComboBox 控件添加項目重複的問題及解決
Copyright ©
程式碼之家 All Rights Reserved