我有一个多线程应用程序,并且 aCancellationToken
用作共享对象。每个线程都可以触发它来告诉其他线程该作业被取消。然后一个线程进行清理并像这样处理每个对象CancellationToken
。然后,如果一个线程尝试使用它,则会引发异常:
CancellationTokenSource 已被释放。
如何在使用之前找出对象已被处置?
我有一个多线程应用程序,并且 aCancellationToken
用作共享对象。每个线程都可以触发它来告诉其他线程该作业被取消。然后一个线程进行清理并像这样处理每个对象CancellationToken
。然后,如果一个线程尝试使用它,则会引发异常:
CancellationTokenSource 已被释放。
如何在使用之前找出对象已被处置?
好吧,根据 Reflector 的说法,CancellationTokenSource
它有一个内部IsDisposed
方法可以告诉你,但由于它是内部的,你不应该调用它。
在任何情况下,如果一个线程抽出其他线程所依赖的数据结构和对象,则不要这样做。修复你的代码,让这些对象在他们需要的时候一直存在。
换句话说,CancellationTokenSource
在你处理它之前等待那些其他线程完成需要它。
正确的做法是让一些 Disposable 对象的创建者稍微违反 Microsoft 的“规则”,即对已处置对象执行任何操作都应该引发异常,而是遵循更一般的规则,即任何时候都应该引发异常无法满足方法的后置条件。如果 Cancel 方法的目的是确保没有人会继续认为作业是活的,甚至在调用 Cancel 方法之前每个人都认为作业是死的,那么该方法的后置条件就满足了。对象是否被释放。
通常,设计良好的对象之外的代码不需要查询它是否已被释放,除非可能断言它已经被释放。相反,对象本身应提供方法,其对已处置对象的含义将是清晰明确的。这些方法可能在内部使用 IsDisposed 标志,但必须使用任何必要的锁定来防止竞争条件。一般来说,模式
如果(!myThing.isDisposed) myThing.DoSomething();
表示 myThing 应该真正支持 DoSomethingIfNotDisposed 方法(可能称为 TryDoSomething)。如果您不能这样做,我的倾向可能是编写您自己的 DoSomethingIfNotDisposed 扩展方法并使用 Try/Catch 来抑制 ObjectDisposedException(或对象将抛出的任何特定异常)。
在使用之前检查对象是否已处置。
仍然不是最好的设计模式。但是,这是我用来确定是否处置对象的方法。
if (!object.IsDisposed) object.DoSomething();
或者
public string DoSomething()
{
if (this.IsDisposed) return null;
}
如果这不起作用,您可以尝试添加 IsDisposed 标志并覆盖 dispose 方法。并在您自己的代码中将其设置为 true。
继承你的类并添加属性:
class MyCancellationTokenSource: CancellationTokenSource
{
public bool MyIsDisposed { get; private set; }
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
MyIsDisposed = true;
}
}