关闭具有WebBrowser控件的表单时为什么会出现RaceOnRCWCleanup错误?

Chr*_*isA 24 .net webbrowser-control rcw winforms

VS2008,.NET 2,VB.NET,XP ......

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

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

从Visual Studio运行应用程序,如果单击"关闭"按钮,表单将关闭,不会出现任何错误.

如果我按下ESC按钮,我会得到

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

如果我在VS外面运行应用程序,我没有错误.

任何想法a)为什么错误,和b)如何预防或抑制它?

提前谢谢了.

Han*_*ant 37

这不是错误,而是一个警告.由托管调试助手(MDA)生成,它是托管代码调试器的扩展,它认为它在代码中出现了问题.鞋子适合.您正在使用RCW,WebBrowser是一个COM控件.你正在杀掉RCW,你正在关闭你的表格.MDA介入,因为它认为它正在使用Web浏览器,并在请求完成之前被杀死.通常只有在代码中使用线程时才有意义.

你是?如果没有,不要失去任何睡眠.COM使用引用计数,因无法解析循环引用而臭名昭着.


好的,我得到了一个repro for this,由评论启用.是的,这是由表单的CancelButton属性或按钮的DialogResult属性触发的.当WB具有焦点时会发生这种情况,它会看到Escape键按下.ActiveX管道的一部分是告诉容器它,以便它可以响应应该有副作用的击键.快捷键击,Tab,Enter.并逃脱.如果该按钮然后关闭窗体,则调试器看到WB在堆栈中存在来自RCW代码的活动堆栈帧时被释放.危险在于,当COM组件被释放后,被调用的代码返回时可能会导致崩溃,这种情况并不少见.

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

    private void CancelButton_Click(object sender, EventArgs e) {
        this.BeginInvoke((MethodInvoker)delegate { this.Close(); });
    }
Run Code Online (Sandbox Code Playgroud)

  • 不,这一切都发生在前台线程上.事实并非如此,这让我感到困扰 - 有很多方法可以在VS中关闭它们.事实上,如果通过单击"关闭"按钮调用Close事件处理程序,则*不会*发生,但如果通过按ESC调用相同的处理程序(因为"关闭"按钮是表单的"取消"按钮属性),则*不*.为什么不同? (2认同)
  • 我看到了这个确切的场景..这对我来说不是问题,因为我想用webBrowser关闭表单.我想了解为什么按ESC和单击'X'之间存在差异. (2认同)