我正在與一個應用程序的Winforms(.NET 3.5 SP1),其具有工作空間的概念,它可以包含面板的n個工作。每個面板(來自Panel
派生)具有視圖:
.-----------------------. |Workspace | |.--------. .--------. | ||Panel1 | |Panel2 | | ||.-----. | |.-----. | | |||View1| | ||View2| | | ||'-----' | |'-----' | | |'--------' '--------' | '-----------------------'
所有面板被添加到集合this.Controls
工作區類(其從UltraTabPageControl
,一個Infragistics的GUI控制導出)。每個視圖都會添加到其父項的Controls
集合中。所以,當在工作區上調用Dispose
時,面板和視圖會自動處理,這是完全預期和期望的。
我們有另一個概念叫做ViewManager
。它可以跟蹤工作區中的所有View
控件,並負責維護一個「主」視圖。每創建一個View
,它都會向該管理器註冊。這將View
添加到列表中,然後運行一些邏輯來確定新的「主」視圖,然後在每個視圖上調用Synchronize()
方法。
當前的設計是,無論何時調用View.Dispose()
,它都會從ViewManager
中註銷自身。這將從列表中刪除View
,然後運行相應的邏輯來檢查剩餘視圖中的新主控。
扭曲
當我們正在關閉整個工作區,存在需要其他面板之前被關閉一個特殊Panel
類型。因此,我們必須在我們的Dispose
方法的代碼看起來像這樣:
protected override void Dispose(bool disposing)
{
var theSpecialPanel = GetSpecialPanel();
if (theSpecialPanel != null)
{
theSpecialPanel.Dispose();
}
base.Dispose(disposing);
}
如果我們採取的是代碼,那麼其他面板可以theSpecialPanel
前佈置。這會導致檢查新主控制面板的邏輯運行,並在每個View
上調用Synchronize()
,包括此特殊面板。這會拋出一個
「InvalidComObjectException:已從其基礎RCW分離的COM對象無法使用。」
問題
這是設計是一個代碼味道?強制執行一個特定的對象在別人之前被處置是否很奇怪?
它肯定看起來不好。如果客戶端代碼不調用Dispose會發生什麼?這是否會導致此異常終止器線程崩潰?這是一個不可違反的例外。閱讀此:http://blogs.msdn.com/b/visualstudio/archive/2010/03/01/marshal-releasecomobject-considered-dangerous.aspx?wa=wsignin1.0 – 2011-03-12 01:33:09
這將是我的下一個問題: ) - 什麼會導致這個異常?感謝指針;正是我所期待的。 – bentsai 2011-03-12 03:34:23
注意:您的Dispose代碼不符合良好做法 - 如果處置== false,則您正在訪問其他託管對象。如果您有自己的非標準析構函數實現,或者如果終結器調用Dispose(false),那麼可能會引起混淆。請參閱http://msdn.microsoft.com/en-us/library/aa720161(v=VS.71).aspx – 2011-03-12 04:02:27