C# 4.0 从事件处理程序对实例调用Dispose是否安全?

C# 4.0 从事件处理程序对实例调用Dispose是否安全?,c#-4.0,idisposable,C# 4.0,Idisposable,很明显,我无法判断任务何时完成,所以在我看来,我可以处理此实例的唯一实际位置是“已完成事件” 这样做安全吗?唉,关于何时调用Dispose安全,没有一般规则。如果微软规定,当对象不在使用时,Dispose必须在任何时候都可以安全调用,那么遵守这样的规则很少会有困难;如果一个类可能并不总是能够立即执行所有必要的清理(*),那么它通常可以设置一个标志和/或安排在下一次机会执行必要的清理。不幸的是,Microsoft没有规定Dispose实现必须处理异步Dispose请求,也没有任何通用方法可用于保存

很明显,我无法判断任务何时完成,所以在我看来,我可以处理此实例的唯一实际位置是“已完成事件”


这样做安全吗?

唉,关于何时调用
Dispose
安全,没有一般规则。如果微软规定,当对象不在使用时,
Dispose
必须在任何时候都可以安全调用,那么遵守这样的规则很少会有困难;如果一个类可能并不总是能够立即执行所有必要的清理(*),那么它通常可以设置一个标志和/或安排在下一次机会执行必要的清理。不幸的是,Microsoft没有规定
Dispose
实现必须处理异步
Dispose
请求,也没有任何通用方法可用于保存对
IDisposable
实例的最后一次有用引用的对象在安全处置时请求通知

尽管对于何时调用Dispose是安全的缺乏保证,但是许多实现
Dispose
的特定类确实提供了何时可以安全调用Dispose的保证。如果知道某个特定对象的类型可以在特定上下文中安全地进行处理,那么就可以进行处理。特别是当对象中的事件可能是在它可能知道的线程上下文中
处置它的唯一机会,并且在事件处理程序中处置对象是有意义的情况下,处置对象应该是安全的。任何正确编写的事件处理程序都应该做好准备,以防发送事件的对象可能在系统决定它们应该运行的时间和它实际运行它们的时间之间被释放


(*)
IDisposable
的基本目的是允许对象通知位于其外部但代表其行事损害其他实体的实体,他们不应再这样做[例如,告诉文件系统不应再授予对象对文件的独占访问权]。这种行动被称为“释放资源”。有人持有对某个对象的最后一个幸存引用这一事实可能意味着没有其他线程可以使用该对象,但并不意味着没有其他线程正在使用其资源需要释放的任何非线程安全实体。

是处置
MyTask
实例所必需的?如果没有必要,它无法实现IDisposable。很抱歉,我的措辞如此糟糕。我只是想知道你在哪里做需要手动处理的事情,因为这是一个相当罕见的要求。我不知道你说的手动是什么意思?您是否将使用与调用Dispose()进行比较#使用#只能用于同步任务,我不认为异步任务是“罕见”的要求。这没有多大意义。如果您希望客户端代码处理对象,那么为什么不在引发事件后处理自己呢?因此,这完全取决于如何实现dispose。如果实现不让实例处于“非功能”状态,则在事件处理程序中调用Dispose不会有什么害处?@Goran:这取决于所讨论的确切对象,但通常情况下,如果对象的所有者打算将其保留到某件事发生时,并且对象的事件会在发生时提供通知,使用该事件处理对象应该是安全的。我可以与任务库进行比较。创建一个任务,然后执行它,任务完成后,将调用传递给ContinueWith的方法。我们能否在此方法中同时处理任务对象(原始任务和ContinueWith返回的任务)?我不想讨论是否有必要处理任务(我知道关于处理WaitHandle的故事),我只需要知道-我们可以吗?
public class MyTask : IDisposable { ... }

MyTask task = new MyTask(() => SomeTask);

task.Completed += (s, e) =>
{
    // do something with result
    ...
    // dispose of this instance
    ((MyTask)s).Dispose();
};

// execute the task
task.Execute();