如何规避内存泄漏的风险

  1. 事件(Event)
    定位:长寿命对象.Event += 短命对象.Method
    规避:Dispose/OnClose 里 -= 或用 WeakEventManager

  2. 静态字段 / 单例
    定位:public static ObservableCollection Cache = … 持有 UI 元素或 VM
    规避:只在静态字段里存“数据”,不存 UIElement、ImageSource 等

  3. DispatcherTimer / System.Timers.Timer
    定位:timer.Tick += UserControl.OnTick,UserControl 关闭后未停止
    规避:OnUnloaded/OnClose 里 timer.Stop() + -=

  4. 绑定到静态或长寿命 Source
    定位:ItemsSource="{x:Static local:Global.Data}" 且 Data 是静态集合
    规避:用 CollectionViewSource 或 BindingOperations.ClearBinding

  5. Image / BitmapImage / HObject 大资源
    定位:Image.Source = new BitmapImage(...) 后不释放,或 Halcon HObject 未 Dispose
    规避:Image.Source = null; bitmapImage.StreamSource?.Dispose(); hobject.Dispose();

  6. DependencyPropertyDescriptor.AddValueChanged
    定位:DependencyPropertyDescriptor.FromProperty(...).AddValueChanged(control, handler)
    规避:RemoveValueChanged 或在 OnClose 里清理

  7. CommandManager.RequerySuggested
    定位:CommandManager.RequerySuggested += handler 未移除
    规避:自定义 ICommand 或用 WeakEventManager

  8. DataTemplate / Style 中的事件
    定位:EventSetter Event="Loaded" Handler="OnLoaded" 在全局 Style 里
    规避:OnUnloaded 里 -=,或避免在全局 Style 里挂事件

  9. 非托管资源(相机、串口、Halcon)
    定位:Camera.Open() / SerialPort.Open() / HalconDotNet.HOperatorSet.OpenWindow() 未关闭
    规避:IDisposable 模式 + OnClose 里统一 Close/Dispose

  10. BindingOperations.EnableCollectionSynchronization
    定位:跨线程集合同步后忘记 DisableCollectionSynchronization
    规避:OnClose 里 BindingOperations.DisableCollectionSynchronization(collection)

   protected override void OnClose()
    {
      // 1. 事件
      SomeLongLifeObj.Event -= MyHandler;

      // 2. 定时器
      timer?.Stop();
      timer.Tick -= MyHandler;

      // 3. 绑定
      BindingOperations.ClearAllBindings(this);

      // 4. 大资源
      Image.Source = null;
      BitmapImage.StreamSource?.Dispose();
      hObject?.Dispose();

      // 5. 非托管
      camera?.Close();
      serialPort?.Close();

      base.OnClose();
    }

记住“长引用短”这四个字,任何长寿命对象(静态、单例、全局集合、全局事件)只要还引用着短命 UI/VM/资源,就会泄漏;在 Dispose/OnClose 里断链即可。

posted @ 2025-08-21 22:29  孤沉  阅读(15)  评论(0)    收藏  举报