27 Stimmen

Warum ein RaceOnRCWCleanup-Fehler beim Schließen eines Formulars mit WebBrowser-Steuerelement auf sie?

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

Ich habe ein Windows-Formular mit einem WebBrowser-Steuerelement und einer Schaltfläche "Schließen", die nur eine Me.Close . Die Schaltfläche "Abbrechen" des Formulars ist auf die Schaltfläche "Schließen" eingestellt, so dass ich das Formular mit ESC schließen kann.

Ich habe die DocumentText Eigenschaft des WebBrowser-Steuerelements im Load-Ereignis, und der HTML-Code wird angezeigt.

Wenn ich die Anwendung in Visual Studio ausführe und auf die Schaltfläche Schließen klicke, wird das Formular ohne Fehler geschlossen.

Wenn ich die ESC-Taste drücke, erhalte ich

R Meldung: Es wurde versucht, eine verwendete einen RCW freizugeben, der in Gebrauch ist. Die RCW wird von dem aktiven Thread oder einem einem anderen Thread. Der Versuch, eine benutzten RCW zu befreien, kann zur Beschädigung oder zum Datenverlust führen.

Wenn ich die Anwendung außerhalb von VS ausführe, erhalte ich keinen Fehler.

Gibt es Ideen, a) warum der Fehler auftritt und b) wie man ihn verhindern oder unterdrücken kann?

Vielen Dank im Voraus.

42voto

Hans Passant Punkte 894572

Es handelt sich nicht um einen Fehler, sondern um eine Warnung. Sie wird von einem Managed Debugging Assistant (MDA) erzeugt, einer Erweiterung des Debuggers für verwalteten Code, der glaubt, dass in Ihrem Code etwas schief läuft. Der Schuh passt. Sie verwenden einen RCW, WebBrowser ist ein COM-Steuerelement. Sie beenden den RCW, Sie schließen Ihr Formular. Der MDA greift ein, weil er glaubt, dass der WebBrowser in Verwendung ist und beendet wird, bevor die Anfrage abgeschlossen ist. Das würde normalerweise nur Sinn machen, wenn Sie einen Thread in Ihrem Code verwenden.

Und Sie? Wenn nicht, sollten Sie sich deswegen keine Sorgen machen. COM verwendet Referenzzählung, berüchtigt für nicht in der Lage, zirkuläre Referenzen aufzulösen.


Okay, ich habe eine Repro dafür, ermöglicht durch die Kommentare. Ja, dies wird durch die CancelButton-Eigenschaft des Formulars oder die DialogResult-Eigenschaft der Schaltfläche ausgelöst. Dies geschieht, wenn die WB den Fokus hat, es sieht die Escape-Taste drücken. Ein Teil der ActiveX-Klempnerarbeit besteht darin, den Container darüber zu informieren, damit er auf Tastendrücke reagieren kann, die einen Nebeneffekt haben sollen. Tastenkombinationen, Tab, Enter. Und Escape. Wenn die Schaltfläche dann das Formular schließt, sieht der Debugger, dass der WB entsorgt wird, während sich aktive Stackframes vom RCW-Code auf dem Stack befinden. Die Gefahr ist, dass dies zu einem Absturz führen kann, wenn der aufgerufene Code zurückkehrt, da die COM-Komponente freigegeben wurde, dies ist nicht ungewöhnlich.

Diesen Absturz zu sehen ist ziemlich unwahrscheinlich, aber ich kann mir vorstellen, dass dies bombardieren könnte, wenn der Finalizer-Thread ausgeführt wird, kurz bevor das Click-Ereignis der Schaltfläche zurückkehrt. Die Abhilfe für die MDA und den möglichen Absturz besteht darin, das Schließen des Formulars zu verzögern, bis der ActiveX-Code nicht mehr ausgeführt wird. Elegant gemacht mit Control.BeginInvoke(). Etwa so:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X