为什么在关闭带有 WebBrowser 控件的窗体时出现 RaceOnRCWCleanup 错误?
VS2008、.NET 2、VB.NET、XP ...
我有一个 Windows 窗体,带有一个 WebBrowser 控件和一个关闭按钮,它只执行 Me.Close
。表单的取消按钮设置为关闭按钮,以便我可以按 ESC 关闭表单。
我在加载事件中设置了 WebBrowser 控件的 DocumentText
属性,然后显示 HTML。
从 Visual Studio 运行应用程序,如果单击“关闭”按钮,窗体将关闭,不会出现错误。
如果我按下 ESC 按钮,我会得到
检测到 RaceOnRCWCleanup 消息:已尝试 释放正在使用的 RCW。 RCW 正在活动线程上使用或 另一个线程。试图释放一个 使用中的 RCW 可能会导致损坏或 数据丢失。
如果我在 VS 之外运行该应用程序,则不会出现错误。
有什么想法a)为什么会出现错误,b)如何防止或抑制它?
非常感谢。
VS2008, .NET 2, VB.NET, XP ...
I have a Windows form, with a WebBrowser control and a Close button, which just does a Me.Close
. The form's cancel button is set to the Close button, so that I can hit ESC to close the form.
I set the DocumentText
property of the WebBrowser control in the load event, and the HTML displays.
Running the application from Visual Studio, if I click the Close button, the form closes with no error.
If I hit the ESC button I get
RaceOnRCWCleanup was detected
Message: An attempt has been made to
free an RCW that is in use. The RCW
is in use on the active thread or
another thread. Attempting to free an
in-use RCW can cause corruption or
data loss.
If I run the app outside VS, I get no error.
Any ideas a) why the error, and b) how to prevent or suppress it?
Many thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这不是错误,而是警告。由托管调试助手 (MDA) 生成,MDA 是托管代码调试器的扩展,它认为它发现代码中出现问题。鞋子合脚。您使用的是RCW,WebBrowser是COM控件。你正在消灭 RCW,你正在关闭你的表格。 MDA 介入是因为它认为它看到了正在使用的 Web 浏览器,并且在请求完成之前就被终止了。通常,只有当您在代码中使用线程时,这才有意义。
你是?如果没有,请不要为此失眠。 COM 使用引用计数,但因无法解决循环引用而臭名昭著。
好的,我得到了这个的重现,通过评论启用。是的,这是由表单的 CancelButton 属性或按钮的 DialogResult 属性触发的。当 WB 获得焦点时会发生这种情况,它会看到按下 Escape 键。 ActiveX 管道的一部分是告诉容器有关它的信息,以便它可以响应应该产生副作用的击键。快捷键,Tab,Enter。和逃脱。如果该按钮随后关闭窗体,则调试器会看到 WB 被释放,同时堆栈上存在来自 RCW 代码的活动堆栈帧。危险在于,当 COM 组件被释放后,调用的代码返回时,这可能会导致崩溃,这种情况并不罕见。
看到这种崩溃的可能性很小,但我可以想象,当终结器线程在按钮的 Click 事件返回之前运行时,这可能会发生爆炸。 MDA 和潜在崩溃的解决方法是延迟关闭表单,直到 ActiveX 代码停止运行。使用 Control.BeginInvoke() 优雅地完成。像这样:
It is not an error, it is a warning. Produced by a Managed Debugging Assistant (MDA), an extension to the debugger for managed code, that thinks it is seeing something going wrong in your code. The shoe fits. You are using an RCW, WebBrowser is an COM control. You are killing off the RCW, you are closing your form. The MDA steps in because it thinks it is seeing the web browser in use and it getting killed before the request is completed. That would normally only make sense if you are using a thread in your code.
Are you? If not, don't lose any sleep over it. COM uses reference counting, notorious for not being able to resolve circular references.
Okay, I got a repro for this, enabled by the comments. Yes, this is triggered by the form's CancelButton property or the button's DialogResult property. This happens when the WB has the focus, it sees the Escape key press. Part of the ActiveX plumbing is to tell the container about it so it can respond to keystrokes that should have a side-effect. Shortcut keystrokes, Tab, Enter. And Escape. If the button then closes the form, the debugger sees the WB getting disposed while there are active stack frames from the RCW code on the stack. The danger is that this might cause a crash when the called code returns since the COM component got released, it isn't uncommon.
Seeing this crash is pretty unlikely, but I can imagine that this could bomb when the finalizer thread runs just before the button's Click event returns. The workaround for the MDA and the potential crash is to delay closing the form until after the ActiveX code stops running. Elegantly done with Control.BeginInvoke(). Like this: