2009-12-09 135 views
20

VS2008,.NET 2,VB.NET,XP ...爲什麼在使用WebBrowser控件關閉窗體時出現RaceOnRCWCleanup錯誤?

我有一個Windows窗體,一個WebBrowser控件和一個關閉按鈕,它只是做一個Me.Close。窗體的取消按鈕設置爲關閉按鈕,以便我可以按ESC鍵關閉窗體。

我在加載事件中設置了WebBrowser控件的DocumentText屬性,並顯示了HTML。

從Visual Studio運行應用程序,如果我單擊「關閉」按鈕,表單將關閉而沒有錯誤。

如果我打的ESC鍵,我得到檢測

RaceOnRCWCleanup 消息:已經嘗試到 免費的RCW是在使用的正確性。 RCW 正在使用活動線程或 另一個線程。試圖釋放使用中的RCW的 可能會導致數據丟失或損壞 。

如果我在VS之外運行應用程序,則不會出現錯誤。

任何想法a)爲什麼錯誤,和b)如何防止或抑制它?

許多在此先感謝。

回答

30

這不是一個錯誤,它是一個警告。由託管調試助手(MDA)生成,它是託管代碼的調試器的擴展,它認爲它在代碼中看到了錯誤。鞋適合。您正在使用RCW,WebBrowser是一個COM控件。你正在殺死RCW,你正在關閉你的表格。因爲MDA認爲它正在使用Web瀏覽器,並且在請求完成之前它已經被殺死,所以MDA步驟進入。這通常只有在你的代碼中使用線程時纔有意義。

是嗎?如果不是的話,不要對它失眠。 COM使用引用計數,臭名昭着的不能解決循環引用。


好的,我有一個repro爲此,由評論啓用。是的,這是由窗體的CancelButton屬性或按鈕的DialogResult屬性觸發的。這發生在WB有焦點時,它看到Escape鍵按下。 ActiveX管道的一部分是告訴容器它可以響應應該有副作用的按鍵。快捷鍵,Tab,Enter。和逃脫。如果按鈕然後關閉表單,則調試器會在堆棧中存在來自RCW代碼的活動堆棧幀時看到WB被丟棄。危險在於,當COM組件被釋放後,被調用的代碼返回時,這可能會導致崩潰,這種情況並不罕見。

看到這個崩潰是不太可能的,但我可以想象,當按鈕的Click事件返回之前終結器線程運行時,這可能會炸彈。 MDA和潛在崩潰的解決方法是延遲關閉表單,直到ActiveX代碼停止運行。使用Control.BeginInvoke()完成優雅。像這樣:

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

不,它都發生在前臺線程上。 事實並非如此令我困擾 - 有些方法可以在VS中關閉它們。事實上,如果通過單擊關閉按鈕調用Close事件處理程序,它將不會發生,但如果通過按ESC調用同一個處理程序(因爲關閉按鈕是窗體的取消按鈕屬性),它*不*。 爲什麼區別? – ChrisA 2009-12-10 09:17:12

+2

我看到了這個確切的場景..這對我來說不是問題,因爲我想用webBrowser關閉窗體。我想了解爲什麼按ESC鍵並點擊'X'有什麼區別。 – mpeterson 2010-02-19 23:07:01

+0

@chris,@mpeterson - 得到了一個repro和一個解決方案,發佈了更新。 – 2010-12-30 19:03:13

相關問題