【问题标题】:WPF - Does HwndSource have to be disposed?WPF - 是否必须处置 HwndSource?
【发布时间】:2016-08-20 19:38:45
【问题描述】:

我在不是主窗口的 WPF 窗口中使用HwndSource,以便挂钩窗口过程 (WndProc) 以接收一些消息:

WinSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
WinSource.AddHook(new HwndSourceHook(WndProc));

HwndSource 实现IDisposable。 MSDN 不清楚我何时/应该处置它。 HwndSource.FromHwnd 的文档解释了上述技术:

您可以使用此方法为不是显式互操作窗口的窗口返回 HwndSource。这个过程是:

  1. 创建一个 WindowInteropHelper 实例(提供主窗口作为构造函数参数)。
  2. 从 WindowInteropHelper 实例中获取 Handle 属性的值。
  3. 将该 HWND 值作为参数传递给 FromHwnd。

然后:

如果您想将一般的 AddHook 消息处理添加到窗口,此技术可能很有用。但是,无论何时创建 HwndSource,您也有责任销毁它。即使应用程序 HwndSource 的 Application 对象被释放也是如此。

(重点是我的)

但是,在HwndSource 类文档中,我们看到:

对象生命周期

HwndSource 是常规公共语言运行时 (CLR) 对象,其生命周期由垃圾收集器管理。因为 HwndSource 表示非托管资源,所以 HwndSource 实现 IDisposable。 [...] 对于某些互操作场景,可能需要从互操作代码中显式调用 Dispose。

关于钩子:

实际的钩子由弱引用持有。因此,请确保您管理钩子委托的生命周期。

【问题讨论】:

    标签: wpf interop idisposable


    【解决方案1】:

    我无法对此给出完整的答案,但根据最近的经验,我可以说您不应该过早地处理 HwndSource 对象 - 具体而言,在它所指的窗口关闭之前完全不要。

    我只是在调试这样一个场景:

    using(var source = HwndSource.FromHwnd(window.HWnd()))
    {
         source.AddHook(hook);
    }
    

    这样做的结果是窗口在源被释放后立即失去功能(不再处理消息)。

    简要查看FromHwnd() 的参考源,它似乎总是会为同一个窗口返回同一个对象。我认为这就是为什么你不能仅仅因为你自己的代码已经完成了它就处置source。显然HwndSource.Dispose() 不只是清理HWndSource 对象,而是一些非托管窗口本身。

    注意到这一点,现在我还看到 HWndSource documentation 说:

    同步调用 Dispose 会立即销毁 Win32 窗口

    这似乎是我观察到的。

    【讨论】:

      猜你喜欢
      • 2011-04-07
      • 1970-01-01
      • 2013-02-13
      • 1970-01-01
      • 1970-01-01
      • 2013-12-05
      • 2013-11-10
      • 2020-01-18
      • 2015-10-26
      相关资源
      最近更新 更多