我有一个多线程应用程序,CancellationToken
用作共享对象。每个线程都可以触发它以告诉其他线程该作业被取消。然后一个线程进行清理并处理像CancellationToken
这样的每个对象。然后,如果线程试图使用它,则会引发异常:
CancellationTokenSource已被处置。
如何在使用之前找出对象?
答案 0 :(得分:4)
嗯,根据Reflector,CancellationTokenSource
有一个内部IsDisposed
方法可以告诉你,但由于它是内部的,你不应该叫它。
在任何情况下,如果一个线程拉出数据结构和其他线程所依赖的对象,则不要这样做。修复您的代码,并在需要的时间内保留这些对象。
换句话说,在处理它之前,等待其他线程完成需要CancellationTokenSource
。
答案 1 :(得分:2)
动作的正确的做法是对于一些一次性物品的创造者,以对抗微软的“规则”小幅使得执行释放的对象的任何行动应该抛出一个异常,而是按照更普遍的规则,异常应是在任何时候无法满足方法的后置条件时抛出。如果取消方法的目的是确保没有人会继续把工作作为生活和取消方法被调用,即使之前大家都认为这项工作作为死了,那么后置条件的方法是满意的,无论对象是否被处置。
通常,精心设计的对象外部的代码不应该查询它是否被处理掉,除非可能断言它已经存在。相反,对象本身应该提供方法,这些方法在被处置对象上的含义将是清晰和明确的。这些方法可能在内部使用IsDisposed标志,但必须使用任何必要的锁定来防止竞争条件。一般来说,模式
if (!myThing.isDisposed) myThing.DoSomething();
表示myThing应该真正支持DoSomethingIfNotDisposed方法(可能称为TryDoSomething)。如果你不能做到这一点,我的倾向可能会写自己的DoSomethingIfNotDisposed扩展方法,并使用一个try / catch扼杀一个的ObjectDisposedException(或任何特定的例外对象将抛出)。
答案 2 :(得分:1)
在使用之前检查对象是否被丢弃。
仍然不是最好的设计模式。但是这里我用的是确定是否处置了一个物体。
if (!object.IsDisposed) object.DoSomething();
或
public string DoSomething()
{
if (this.IsDisposed) return null;
}
如果这不起作用,您可以尝试添加IsDisposed标志并覆盖dispose方法。并在您自己的代码中将其设置为true。
答案 3 :(得分:0)
继承您的类并添加属性:
class MyCancellationTokenSource: CancellationTokenSource
{
public bool MyIsDisposed { get; private set; }
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
MyIsDisposed = true;
}
}