Why a RaceOnRCWCleanup error when closing a form with WebBrowser control on it?
Asked Answered
H

1

27

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.

Highkeyed answered 9/12, 2009 at 15:9 Comment(0)
C
42

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:

    private void CancelButton_Click(object sender, EventArgs e) {
        this.BeginInvoke((MethodInvoker)delegate { this.Close(); });
    }
Crabstick answered 10/12, 2009 at 2:24 Comment(7)
No, it's all happening on the foreground thread. It's not the fact that it's happening at all that bothers me - there are ways of switching them off in VS. It's the fact that if the Close event handler is invoked by clicking the Close button, it doesn't happen, but if the same handler is invoked by hitting ESC (since the Close button is the form's Cancel button property), it does. Why the difference?Highkeyed
I'm seeing this exact scenario.. it isn't a problem for me, because I WANT to close the form with the webBrowser on it. I would like to understand why there is a difference between pressing ESC and clicking the 'X'.Borkowski
@chris, @Borkowski - got a repro and a solution, post updated.Crabstick
great stuff, thanks very much. I've implemented a very similar code fragment in VB, and it works a treat.Highkeyed
Is "Managed Debugging Assistant" the same as the "Exception Assistant"? -- How do you turn off this warning? (I've unchecked the box but it still displays every time.)Aciniform
Figured it out -- MDA can be configured from the "Exceptions" dialog (Ctrl+D,E by default), but by default you can't uncheck this guy, the option is grayed out. Once you go into your debugger properties and disable "Just my code" it give you the option to disable this guy.Aciniform
though it's not Initilized in the form, but still i could reach the main thread using this, i think it's the reason, behind why this worked for me.Fluorine

© 2022 - 2024 — McMap. All rights reserved.