為什麼關閉帶有 WebBrowser 控制項的表單時出現 RaceOnRCWCleanup 錯誤?
VS2008、.NET 2、VB.NET、XP …
我有一個 Windows 窗體,帶有一個 WebBrowser 控制項和一個關閉按鈕,它只執行
Me.Close. 表單的取消按鈕設置為關閉按鈕,這樣我就可以按 ESC 關閉表單。我
DocumentText在載入事件中設置了 WebBrowser 控制項的屬性,並顯示了 HTML。從 Visual Studio 執行應用程序,如果點擊“關閉”按鈕,表單將關閉且沒有錯誤。
如果我按下 ESC 按鈕,我會得到
檢測到 RaceOnRCWCleanup 消息:已嘗試釋放正在使用的 RCW。RCW 正在活動執行緒或其他執行緒上使用。嘗試釋放正在使用的 RCW 可能會導致損壞或數據失去。
如果我在 VS 之外執行應用程序,我不會收到任何錯誤。
任何想法a)為什麼會出現錯誤,以及b)如何防止或抑制它?
提前謝謝了。
這不是錯誤,而是警告。由託管調試助手 (MDA) 生成,它是託管程式碼調試器的擴展,它認為它在您的程式碼中發現了問題。鞋子合腳。您正在使用 RCW,WebBrowser 是一個 COM 控制項。你正在扼殺 RCW,你正在關閉你的表格。MDA 介入是因為它認為它看到了正在使用的 Web 瀏覽器,並且在請求完成之前它就被殺死了。這通常只有在您在程式碼中使用執行緒時才有意義。
你是?如果沒有,請不要為此失眠。COM 使用引用計數,因無法解析循環引用而臭名昭著。
好的,我得到了一個重現,由評論啟用。是的,這是由表單的 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(); }); }