释放HwndSource后调用Window的close()引发System.NullReferenceException
问题描述
从MainWindow中调用new Window1().ShowDialog();,当对HwndSource调用Dispose()后再调用Window的Close()时,会触发异常:
An unhandled exception of type 'System.NullReferenceException' occurred in PresentationFramework.dll Object reference not set to an instance of an object.
若不调用Dispose(),后续可能会出现哪些问题?
public partial class Window1 : Window { private const int MESSAGE_CAPTURED_OK = 0x0400 + 6; private HwndSource source; public Window1() { InitializeComponent(); Closing += Window_Closing; } private void Close_Click(object sender, RoutedEventArgs e) => this.Close(); protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); var FormHandle = new WindowInteropHelper(this).Handle; source = HwndSource.FromHwnd(FormHandle); source.AddHook(WndProc); } IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { // Handle messages... if (msg == MESSAGE_CAPTURED_OK) { // operations } return IntPtr.Zero; } private void Window_Closing(object sender, CancelEventArgs e) { source.RemoveHook(WndProc); //source.Dispose(); This line rises error } }
回答
不调用HwndSource.Dispose()可能带来以下问题:
- 内存泄漏:
HwndSource封装的原生窗口资源(如HWND句柄、消息钩子)无法及时被操作系统回收,反复打开关闭Window1会导致内存占用持续升高。 - 残留消息干扰:即便调用了
RemoveHook(WndProc),未释放的HwndSource可能残留底层钩子注册,后续其他窗口的消息处理可能被意外触发或干扰。 - 系统资源耗尽:
HwndSource关联的GDI/USER资源属于操作系统有限资源,长期不释放会导致资源耗尽,影响自身或其他程序运行。 - 垃圾回收延迟:未释放的
HwndSource会延长对象生命周期,直到.NET触发全量垃圾回收才会清理,导致应用内存波动大、响应变慢。
另外,你遇到的调用Dispose()后空引用异常,是因为HwndSource.Dispose()会直接销毁原生窗口资源,而Window.Close()内部还会访问这些已释放的资源。正确做法是不用手动调用HwndSource.Dispose(),Window关闭时会自动清理关联的HwndSource资源,只需确保移除钩子即可。
内容的提问来源于stack exchange,提问作者Sayed Naweed
相关产品推荐
相关产品推荐

