【问题标题】:Unhandled NullReference exception when closing WPF application关闭 WPF 应用程序时未处理的 NullReference 异常
【发布时间】:2014-06-16 22:39:05
【问题描述】:

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

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

附加信息:对象引用未设置为 对象。

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

一些注意事项:

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

调用栈是:

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

以前有人见过吗,或者有人知道如何调试吗?奇怪的是没有调用堆栈,而且它在程序退出时发生。

【问题讨论】:

  • 我认为您需要编辑此问题以将 ShutdownMode 包含在您的 app.xaml 文件中。
  • ShutdownMode属性设置为OnMainWindowClose,但是在启动过程中有几个可以触发的对话框,所以在App启动过程中暂时切换为OnExplicitShutdown,但它是总是在主窗口打开之前切换回OnMainWindowClose
  • 我不知道是什么导致了异常,但我会尝试通过从另一个重定向 Stderr/Stdio 流和希望的应用程序启动它来调试它(绝对 hope ) 在这些流中存在提供线索的人工制品。
  • Visual Studio 已经这样做了(通过“输出”窗口),除了已经提到的内容之外没有任何意义。
  • 嗯,不,实际上控制台错误流没有显示在 vs 输出窗口中。因此,我建议它可能值得检查任何人工制品。

标签: c# wpf


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您的问题缺乏细节,堆栈跟踪很短,但为潜在问题提供了很多线索。一些可见的事实:

    • 异常发生在终结器线程上,这是堆栈跟踪如此短的原因。终结器中未处理的异常是致命的,它们总是会终止程序。尝试在代码中使用 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 事件并触发崩溃,现在您可以捕获它。当发生这种情况时,请务必考虑关闭您的程序,您的进程中确实有一个死尸,当您尝试恢复它时会变成僵尸。

    【讨论】:

    • 我确实使用了 WebBrowser 控件(您能够从堆栈跟踪中看出这一点令人印象深刻),我将尝试手动处理它,看看是否有补救措施问题。仅供参考,该应用程序已经针对 .NET 4,因此它必须像以前的版本一样处理事情。测试完我会在这里更新。
    • 好的,取消那个,好像刚刚搬家了。
    • 看来这就是问题所在!我处理了 WebBrowser 并丢弃了来自它的任何异常,并且应用程序现在干净地关闭了。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多