关闭WPF应用程序时出现未处理的NullReference异常

时间:2014-04-30 14:33:52

标签: c# wpf

当我关闭最后一个窗口时,我的应用程序中出现了未处理的异常:

  

类型'System.NullReferenceException'的未处理异常   发生在PresentationFramework.dll

中      

附加信息:对象引用未设置为的实例   对象

只有在应用程序的生命周期内,我通过我设置的某个进程打开子窗口时才会出现这种情况。该窗口存在于另一个程序集中,该程序集在运行时使用MEF动态加载,然后使用Castle进行实例化。如果我然后调用某个方法,它会创建一个新的STA线程并打开一个WPF对话窗口。

一些警告:

  • 这只发生在某些机器/环境上(虽然我无法识别模式)
  • 我在应用程序的调度程序上有一个UnhandledException处理程序,它捕获所有未处理的异常。这没有被抓住。

调用堆栈是:

PresentationFramework.dll!MS.Internal.Controls.ConnectionPointCookie.Disconnect()
PresentationFramework.dll!MS.Internal.Controls.ConnectionPointCookie.Finalize()

有没有人见过这个,或者有人知道如何调试这个?奇怪的是,没有调用堆栈,它在程序退出时正确发生。

2 个答案:

答案 0 :(得分:13)

你的问题没有细节,堆栈跟踪很短,但提供了许多解决潜在问题的线索。一些明显的事实:

  • 在终结器线程上发生异常,这是堆栈跟踪如此短暂的原因。终结器中未处理的异常是致命的,他们总是会终止该程序。尝试在代码中使用try / catch的原因没有效果。
  • 连接点cookie是一个COM术语,当您订阅COM事件时,您会得到一个。当你取消订阅事件时,需要再次使用该cookie,这在终结器中会发生。 WPF中只有一个类使用它,即WebBrowser控件。 WPF类是Internet Explorer的一个包装器,它是一个COM组件。
  • 该异常虽然具有托管异常名称,但不是由托管代码引起的。终结器已经检查了空引用,它是Internet Explorer,它引发了一个非托管的AccessViolationException。这些由CLR以完全相同的方式处理,因为它们具有完全相同的原因,终结器除此之外没有做任何事情以使区别更清楚。非托管代码与托管代码一样容易受到攻击。更重要的是,堆损坏是一个非常常见的原因。
  • 终结器已经捕获了所有异常,但是NRE只是critical exception所以它会重新抛出它,这就是程序的结束。

使用WebBrowser是一种负担,浏览器通常容易崩溃。当您在应用程序中使用该控件时,它会被放大,它在进程中运行,并且没有Internet Explorer本身使用的那种崩溃保护。因此,浏览器中出现问题的任何内容都会直接影响应用程序的稳定性,因为它是非常难以诊断的崩溃原因,因为它是非托管代码,可能会发生爆炸。

此类崩溃重复得非常糟糕,这是您自己无法获得重复的核心原因。浏览器中最常见的麻烦制造者是加载项,ActiveX控件(如Flash)和反恶意软件。如果您无法控制导航网站的类型,那么您会遇到额外的麻烦,有很多可以故意探测浏览器的漏洞。

您可以使用一种特定的对策,在不再使用时调用控件的Dispose()方法。通常在Window的Closing事件处理程序中。这将立即取消注册COM事件并触发崩溃,现在您可以捕获它。强烈考虑在发生这种情况时关闭你的程序,你的过程中确实有一个死尸,当你试图恢复它时会变成一个僵尸。

答案 1 :(得分:1)

我在其中一个应用程序中遇到了同样的问题,但从未发现它背后的真正问题。但我找到了这个应用程序的解决方法。在主窗口的Closing事件中,我实现了一个关闭所有其他窗口的循环。然后它奏效了。也许这对你也有用。如果你发现它会更好的原因。