在暴露Begin / End方法的类中实现IDisposable

时间:2013-01-29 06:42:48

标签: c# .net dispose

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

我是否有责任在Dispose()BeginLongOperation()的来电之间处理对EndLongOperation()的来电?

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

4 个答案:

答案 0 :(得分:4)

  

我的班级负责处理之间的Dispose()调用   调用BeginLongOperation()和EndLongOperation()?

不,你的班级来电者有责任妥善处理它。这可以在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"));

答案 1 :(得分:1)

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

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

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

因此,我认为您负责保护您的代码免受任何可能的情况,甚至是针对开始和结束之间的(不期望的)调用。

LATER EDIT:当然,正如其他人在这里告诉你的那样,你班级用户的责任就是正确使用它,但我不会依赖于此。如您所知,当对象的最后一个引用消失时,您的对象将被垃圾收集。即使在非异步/单线程设计中,这种错误的使用模式确实可以确定在开始/结束之间调用Dispose()。

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

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

  

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

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

所以开发人员有责任使用你的类来调用Dispose()。