.net 为什么在关闭带有WebBrowser控件的表单时出现RaceOnRCWCleanup错误?

.net 为什么在关闭带有WebBrowser控件的表单时出现RaceOnRCWCleanup错误?,.net,winforms,webbrowser-control,rcw,.net,Winforms,Webbrowser Control,Rcw,VS2008、.NET2、VB.NET、XP 我有一个Windows窗体,带有一个WebBrowser控件和一个Close按钮,它只执行一个Me.Close。表单的“取消”按钮设置为“关闭”按钮,以便我可以按ESC键关闭表单 我在load事件中设置WebBrowser控件的DocumentText属性,HTML显示 从VisualStudio运行应用程序时,如果单击“关闭”按钮,则表单将无错误地关闭 如果我按ESC按钮,我会 检测到RaceOnRCWCleanup 消息:已尝试访问 释放正在使用

VS2008、.NET2、VB.NET、XP

我有一个Windows窗体,带有一个WebBrowser控件和一个Close按钮,它只执行一个
Me.Close
。表单的“取消”按钮设置为“关闭”按钮,以便我可以按ESC键关闭表单

我在load事件中设置WebBrowser控件的
DocumentText
属性,HTML显示

从VisualStudio运行应用程序时,如果单击“关闭”按钮,则表单将无错误地关闭

如果我按ESC按钮,我会

检测到RaceOnRCWCleanup 消息:已尝试访问 释放正在使用的RCW。RCW 正在活动线程上使用,或 另一条线。试图释放一个 使用中的RCW可能导致损坏或损坏 数据丢失

如果我在VS之外运行应用程序,则不会出现错误

有什么想法吗a)为什么会出现错误,以及b)如何防止或抑制错误


非常感谢。这不是一个错误,而是一个警告。由托管调试助手(MDA)生成,MDA是托管代码调试器的扩展,它认为自己看到了代码中的错误。这鞋合脚。您使用的是RCW,WebBrowser是COM控件。你正在删除RCW,你正在关闭你的表格。MDA介入是因为它认为它看到web浏览器正在使用,并且它在请求完成之前就被杀死了。这通常只有在代码中使用线程时才有意义

是吗?如果没有,不要为此而失眠。COM使用引用计数,因为无法解析循环引用而臭名昭著


好的,我得到了一个复制,通过评论。是,这是由窗体的CancelButton属性或按钮的DialogResult属性触发的。当WB有焦点时,它会看到按Escape键。ActiveX管道的一部分是告诉容器有关它的信息,以便它能够响应可能产生副作用的击键。快捷键击、制表符、输入。然后逃走。如果该按钮随后关闭表单,调试器将看到WB被释放,而堆栈上有来自RCW代码的活动堆栈帧。危险在于,在COM组件发布后被调用的代码返回时,这可能会导致崩溃,这并不少见

看到这种崩溃是不太可能的,但我可以想象,当finalizer线程在按钮的Click事件返回之前运行时,这种崩溃可能会爆炸。MDA和潜在崩溃的解决方法是延迟关闭表单,直到ActiveX代码停止运行。使用Control.BeginInvoke()优雅地完成。像这样:

    private void CancelButton_Click(object sender, EventArgs e) {
        this.BeginInvoke((MethodInvoker)delegate { this.Close(); });
    }

不,这一切都发生在前台线程上。困扰我的不是它正在发生的事实——在VS中有关闭它们的方法。事实是,如果通过单击Close按钮调用Close事件处理程序,它不会发生,但是如果通过按ESC调用相同的处理程序(因为Close按钮是窗体的Cancel button属性),它会发生。为什么会有不同?我看到的正是这种情况。。这对我来说不是问题,因为我想用webBrowser关闭表单。我想了解为什么按ESC键和单击“X”键之间有区别。@chris,@mpeterson-得到了一个复制和解决方案,更新后。非常好,谢谢。我在VB中实现了一个非常类似的代码片段,它起到了很好的作用。我发现——MDA可以从“异常”对话框(默认为Ctrl+D,E)中配置,但默认情况下不能取消选中该选项,该选项是灰色的。一旦进入调试器属性并禁用“仅限我的代码”,它将为您提供禁用这家伙的选项。