假设我有一个使用标准 Begin/End 模式公开BeginLongOperation()
和方法的类,并实现.EndLongOperation()
IDisposable
我的班级有责任处理对和的调用Dispose()
之间的调用吗?BeginLongOperation()
EndLongOperation()
如果是这样,这样做的正确方法是什么?
在对 BeginLongOperation() 和 EndLongOperation() 的调用之间处理对 Dispose() 的调用是我的班级的责任吗?
不,你的班级的调用者有责任妥善处理它。这可以在EndLongOperation
方法中完成。您不能将实例包装在using
语句中,因为该BeginLongOperation
方法将立即返回。
示例WebClient
:
var client = new WebClient();
client.DownloadStringCompleted += (sender, e) =>
{
try
{
if (e.Error == null)
{
Console.WriteLine(e.Result);
}
}
finally
{
((WebClient)sender).Dispose();
}
};
client.DownloadStringAsync(new Uri("http://www.google.com"));
我假设 Begin/End 方法是异步的。或者,您的对象可以从另一个线程进行操作。
首先,您需要确定是否真的需要处置您的类的实例。如果是这样,您需要设计 Dispose() 方法(您的类应该实现IDisposable接口),使其不会干扰正在执行的长时间操作。好吧,这取决于您要实施什么策略:您是要等待长操作完成,还是调用 Dispose() 方法应该中断长操作?
通常你永远不会从你的类内部代码中调用 Dispose() 方法,但实际上你需要保护 Dispose() 调用不被不当使用。
所以我认为这是你的责任来保护你的代码免受任何可能的情况,即使是在开始和结束之间的(不希望的)调用。
后期编辑:当然,正如这里的其他人告诉你的那样,你班级用户的责任是正确使用它,但我不会依赖这个。如您所知,当您的对象的最后一个引用消失时,您的对象就会被垃圾回收。即使在非异步/单线程设计中,这种糟糕的使用模式确实可以确定在 Start/End 之间对 Dispose() 的调用。
您不应在 using 块中声明此类的对象,而应尝试手动处理它。
您可以在使用此对象的类的 EndLongOperation 处理程序中调用此类类的处置。
IDisposable 背后的想法如下,我认为这也回答了您的问题。
该接口的主要用途是释放非托管资源。当不再使用该对象时,垃圾收集器会自动释放分配给托管对象的内存。但是,无法预测垃圾收集何时发生。此外,垃圾收集器不了解非托管资源,例如窗口句柄或打开的文件和流。
使用此接口的 Dispose 方法与垃圾收集器一起显式释放非托管资源。当不再需要对象时,对象的使用者可以调用此方法。
因此,使用您的类调用 Dispose() 的开发人员有责任。