简体   繁体   English

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

[英]Unhandled NullReference exception when closing WPF application

I'm getting an unhandled exception in my application when I close the last window: 当我关闭最后一个窗口时,我的应用程序中出现了未处理的异常:

An unhandled exception of type 'System.NullReferenceException' occurred in PresentationFramework.dll PresentationFramework.dll中出现未处理的“System.NullReferenceException”类型异常

Additional information: Object reference not set to an instance of an object. 附加信息:未将对象引用设置为对象的实例。

This only occurs if, during the application's lifetime, I open a child window through a certain process that I have set up. 只有在应用程序的生命周期中,我通过我设置的某个进程打开子窗口时才会出现这种情况。 The window exists in another assembly that is loaded at runtime dynamically with MEF, and then instantiated with Castle. 该窗口存在于另一个程序集中,该程序集在运行时使用MEF动态加载,然后使用Castle进行实例化。 If I then call a certain method, it creates a new STA thread and opens a WPF dialog window. 如果我然后调用某个方法,它会创建一个新的STA线程并打开一个WPF对话框窗口。

Some caveats: 一些警告:

  • This only happens on certain machines/environments (I'm not able to discern a pattern though) 这只发生在某些机器/环境中(虽然我无法识别模式)
  • I have an UnhandledException handler on the dispatcher for the application which catches all unhandled exceptions. 我在应用程序的调度程序上有一个UnhandledException处理程序,它捕获所有未处理的异常。 This is not caught by that. 这没有被抓住。

The call stack is: 调用堆栈是:

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

Has anyone seen this before, or would anyone know how to debug this? 有没有人见过这个,或者有人知道如何调试这个? It's strange that there's no call stack and it happens right as the program is exiting. 奇怪的是,没有调用堆栈,它在程序退出时正确发生。

Your question is devoid of details and the stack trace is short but gives lots of clues towards the underlying problem. 你的问题没有细节,堆栈跟踪很短,但提供了很多线索来解决潜在的问题。 Some visible facts: 一些明显的事实:

  • the exception occurs on the finalizer thread, the reason the stack trace is so short. 终结器线程发生异常,堆栈跟踪如此短暂的原因。 An unhandled exception in a finalizer is fatal, they'll always terminate the program. 终结器中未处理的异常是致命的,它们将始终终止程序。 The reason that trying to use try/catch in your code had no effect. 尝试在代码中使用try / catch的原因没有效果。
  • a connection-point cookie is a COM term, you get one when you subscribe a COM event. 连接点cookie是一个COM术语,当您订阅COM事件时,您将得到一个。 That cookie needs to be used again when you unsubscribe the event, that happens in the finalizer. 当你取消订阅事件时,需要再次使用该cookie,这在终结器中会发生。 There is only one class in WPF that uses it, the WebBrowser control. WPF中只有一个类使用它,即WebBrowser控件。 The WPF class is a wrapper around Internet Explorer, a COM component. WPF类是Internet Explorer的一个包装器,它是一个COM组件。
  • the exception, while it has a managed exception name, is not caused by managed code. 该异常虽然具有托管异常名称,但不是由托管代码引起的。 The finalizer already checks for null references, it is Internet Explorer that throws an unmanaged AccessViolationException under the hood. 终结器已经检查了空引用,它是Internet Explorer,它引发了一个非托管的AccessViolationException。 These are treated the exact same way by the CLR since they have the exact same cause, the finalizer doesn't otherwise do anything to make the distinction clearer. 这些由CLR以完全相同的方式处理,因为它们具有完全相同的原因,终结器不会做任何事情来使区别更清楚。 Unmanaged code is just as vulnerable as managed code to null pointers. 非托管代码与托管代码一样容易受到攻击。 More so, heap corruption is a very common cause. 更重要的是,堆损坏是一个非常常见的原因。
  • the finalizer already catches all exceptions, an NRE is however a critical exception so it rethrows it, that's the end of your program. 终结器已经捕获了所有异常,然而NRE是一个关键异常,因此它重新抛出它,这就是程序的结束。

Using WebBrowser is a liability, browsers in general are rather crash-prone. 使用WebBrowser是一种负担,浏览器通常容易崩溃。 This is amplified when you use the control in your app, it runs in-process and doesn't have the kind of crash protection that Internet Explorer itself uses. 当您在应用程序中使用该控件时,它会被放大,它在进程中运行,并且没有Internet Explorer本身使用的那种崩溃保护。 So anything that goes wrong in the browser will directly affect the stability of your app, often with a very hard to diagnose crash reason since it is unmanaged code that bombs. 因此,浏览器中出现问题的任何内容都会直接影响应用程序的稳定性,因为它是非常难以诊断的崩溃原因,因为它是非托管代码。

And such crashes repeat very poorly, the core reason that you trouble getting a repro for it yourself. 这样的崩溃重演非常糟糕,这是你自己无法获得重复的核心原因。 The most common troublemakers in browsers are add-ins, ActiveX controls (like Flash) and anti-malware. 浏览器中最常见的麻烦制造者是加载项,ActiveX控件(如Flash)和反恶意软件。 You'll have extra trouble if you can't control the kind of web sites that are navigated, there are plenty that probe a browser for vulnerabilities intentionally. 如果您无法控制导航的网站类型,那么您会遇到额外的麻烦,有很多可以故意探测浏览器的漏洞。

There is one specific countermeasure you can use, call the control's Dispose() method when you no longer use it. 您可以使用一个特定的对策,当您不再使用它时调用控件的Dispose()方法。 Typically in the Window's Closing event handler. 通常在Window的Closing事件处理程序中。 That will immediately unregister the COM event and trigger the crash, now you can catch it. 这将立即取消注册COM事件并触发崩溃,现在您可以捕获它。 Do strongly consider shutting down your program when that happens, you do have a dead corpse in your process that will turn in a zombie when you try to revive it. 强烈考虑在发生这种情况时关闭你的程序,你的进程中确实有一个死尸,当你试图恢复它时会变成一个僵尸。

I had the same problem in one of my applications and never found the real problem behind it. 我在我的一个应用程序中遇到了同样的问题,从未发现它背后的真正问题。 But I found a workaround for this application. 但我找到了这个应用程序的解决方法。 At Closing event of the main window I implemented a loop that closed all other windows before. 在主窗口的Closing事件中,我实现了一个关闭所有其他窗口的循环。 Then it worked. 然后它奏效了。 Maybe this could work for you too. 也许这对你也有用。 If you find the reason it would be even better. 如果你找到它会更好的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM