如何规避内存泄漏的风险
-
事件(Event)
定位:长寿命对象.Event += 短命对象.Method
规避:Dispose/OnClose 里 -= 或用 WeakEventManager -
静态字段 / 单例
定位:public static ObservableCollectionCache = … 持有 UI 元素或 VM
规避:只在静态字段里存“数据”,不存 UIElement、ImageSource 等 -
DispatcherTimer / System.Timers.Timer
定位:timer.Tick += UserControl.OnTick,UserControl 关闭后未停止
规避:OnUnloaded/OnClose 里 timer.Stop() + -= -
绑定到静态或长寿命 Source
定位:ItemsSource="{x:Static local:Global.Data}" 且 Data 是静态集合
规避:用 CollectionViewSource 或 BindingOperations.ClearBinding -
Image / BitmapImage / HObject 大资源
定位:Image.Source = new BitmapImage(...) 后不释放,或 Halcon HObject 未 Dispose
规避:Image.Source = null; bitmapImage.StreamSource?.Dispose(); hobject.Dispose(); -
DependencyPropertyDescriptor.AddValueChanged
定位:DependencyPropertyDescriptor.FromProperty(...).AddValueChanged(control, handler)
规避:RemoveValueChanged 或在 OnClose 里清理 -
CommandManager.RequerySuggested
定位:CommandManager.RequerySuggested += handler 未移除
规避:自定义 ICommand 或用 WeakEventManager -
DataTemplate / Style 中的事件
定位:EventSetter Event="Loaded" Handler="OnLoaded" 在全局 Style 里
规避:OnUnloaded 里 -=,或避免在全局 Style 里挂事件 -
非托管资源(相机、串口、Halcon)
定位:Camera.Open() / SerialPort.Open() / HalconDotNet.HOperatorSet.OpenWindow() 未关闭
规避:IDisposable 模式 + OnClose 里统一 Close/Dispose -
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 里断链即可。

浙公网安备 33010602011771号