8

假设我有一个使用标准 Begin/End 模式公开BeginLongOperation()和方法的类,并实现.EndLongOperation()IDisposable

我的班级有责任处理对和的调用Dispose()之间的调用吗?BeginLongOperation()EndLongOperation()

如果是这样,这样做的正确方法是什么?

4

4 回答 4

4

在对 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"));
于 2013-01-29T06:45:50.583 回答
1

我假设 Begin/End 方法是异步的。或者,您的对象可以从另一个线程进行操作。

首先,您需要确定是否真的需要处置您的类的实例。如果是这样,您需要设计 Dispose() 方法(您的类应该实现IDisposable接口),使其不会干扰正在执行的长时间操作。好吧,这取决于您要实施什么策略:您是要等待长操作完成,还是调用 Dispose() 方法应该中断长操作?

通常你永远不会从你的类内部代码中调用 Dispose() 方法,但实际上你需要保护 Dispose() 调用不被不当使用。

所以我认为这是你的责任来保护你的代码免受任何可能的情况,即使是在开始和结束之间的(不希望的)调用。

后期编辑:当然,正如这里的其他人告诉你的那样,你班级用户的责任是正确使用它,但我不会依赖这个。如您所知,当您的对象的最后一个引用消失时,您的对象就会被垃圾回收。即使在非异步/单线程设计中,这种糟糕的使用模式确实可以确定在 Start/End 之间对 Dispose() 的调用。

于 2013-01-29T07:08:05.750 回答
0

您不应在 using 块中声明此类的对象,而应尝试手动处理它。

您可以在使用此对象的类的 EndLongOperation 处理程序中调用此类类的处置。

于 2013-01-29T06:47:31.183 回答
0

IDisposable 背后的想法如下,我认为这也回答了您的问题。

该接口的主要用途是释放非托管资源。当不再使用该对象时,垃圾收集器会自动释放分配给托管对象的内存。但是,无法预测垃圾收集何时发生。此外,垃圾收集器不了解非托管资源,例如窗口句柄或打开的文件和流。

使用此接口的 Dispose 方法与垃圾收集器一起显式释放非托管资源。当不再需要对象时,对象的使用者可以调用此方法。

因此,使用您的类调用 Dispose() 的开发人员有责任。

于 2013-01-29T08:13:55.743 回答