.net 关闭带有 WebBrowser 控件的表单时,为什么会出现 RaceOnRCWCleanup 错误?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1874496/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why a RaceOnRCWCleanup error when closing a form with WebBrowser control on it?
提问by ChrisA
VS2008, .NET 2, VB.NET, XP ...
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.
我有一个 Windows 窗体,带有一个 WebBrowser 控件和一个关闭按钮,它只执行Me.Close. 窗体的取消按钮设置为关闭按钮,以便我可以按 ESC 关闭窗体。
I set the DocumentTextproperty of the WebBrowser control in the load event, and the HTML displays.
我DocumentText在加载事件中设置了WebBrowser 控件的属性,然后 HTML 显示出来。
Running the application from Visual Studio, if I click the Close button, the form closes with no error.
从 Visual Studio 运行应用程序,如果我单击“关闭”按钮,表单将关闭且没有错误。
If I hit the ESC button I get
如果我按下 ESC 按钮,我会得到
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.
检测到 RaceOnRCWCleanup 消息:已尝试释放正在使用的 RCW。RCW 正在活动线程或另一个线程上使用。尝试释放正在使用的 RCW 可能会导致损坏或数据丢失。
If I run the app outside VS, I get no error.
如果我在 VS 之外运行该应用程序,则不会出错。
Any ideas a) why the error, and b) how to prevent or suppress it?
任何想法 a) 为什么会出现错误,以及 b) 如何防止或抑制它?
Many thanks in advance.
提前谢谢了。
回答by Hans Passant
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.
这不是错误,而是警告。由托管调试助手 (MDA) 生成,它是托管代码调试器的扩展,它认为您的代码出现问题。鞋子合脚。您使用的是 RCW,WebBrowser 是一个 COM 控件。您正在杀死 RCW,您正在关闭您的表格。MDA 介入是因为它认为它看到了正在使用的 Web 浏览器,并且在请求完成之前它就被杀死了。这通常只有在您在代码中使用线程时才有意义。
Are you? If not, don't lose any sleep over it. COM uses reference counting, notorious for not being able to resolve circular references.
你是?如果没有,不要为此失眠。COM 使用引用计数,因无法解析循环引用而臭名昭著。
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.
好的,我得到了一个repro,由评论启用。是的,这是由表单的 CancelButton 属性或按钮的 DialogResult 属性触发的。当 WB 获得焦点时会发生这种情况,它会看到 Escape 键按下。ActiveX 管道的一部分是将其告知容器,以便它可以响应应该具有副作用的击键。快捷键,Tab,Enter。和逃脱。如果按钮然后关闭窗体,调试器会看到 WB 被释放,而堆栈上有来自 RCW 代码的活动堆栈帧。危险在于,由于 COM 组件被释放,当被调用的代码返回时,这可能会导致崩溃,这种情况并不少见。
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:
看到这种崩溃的可能性很小,但我可以想象,当终结器线程在按钮的 Click 事件返回之前运行时,这可能会爆炸。MDA 和潜在崩溃的解决方法是延迟关闭表单,直到 ActiveX 代码停止运行。使用 Control.BeginInvoke() 优雅地完成。像这样:
private void CancelButton_Click(object sender, EventArgs e) {
this.BeginInvoke((MethodInvoker)delegate { this.Close(); });
}

