我正在与一个应用程序的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