7

我有一个多线程应用程序,并且 aCancellationToken用作共享对象。每个线程都可以触发它来告诉其他线程该作业被取消。然后一个线程进行清理并像这样处理每个对象CancellationToken。然后,如果一个线程尝试使用它,则会引发异常:

CancellationTokenSource 已被释放。

如何在使用之前找出对象已被处置?

4

4 回答 4

4

好吧,根据 Reflector 的说法,CancellationTokenSource它有一个内部IsDisposed方法可以告诉你,但由于它是内部的,你不应该调用它。

在任何情况下,如果一个线程抽出其他线程所依赖的数据结构和对象,则不要这样做。修复你的代码,让这些对象在他们需要的时候一直存在。

换句话说,CancellationTokenSource在你处理它之前等待那些其他线程完成需要它。

于 2011-04-13T20:47:05.493 回答
3

正确的做法是让一些 Disposable 对象的创建者稍微违反 Microsoft 的“规则”,即对已处置对象执行任何操作都应该引发异常,而是遵循更一般的规则,即任何时候都应该引发异常无法满足方法的后置条件。如果 Cancel 方法的目的是确保没有人会继续认为作业是活的,甚至在调用 Cancel 方法之前每个人都认为作业是死的,那么该方法的后置条件就满足了。对象是否被释放。

通常,设计良好的对象之外的代码不需要查询它是否已被释放,除非可能断言它已经被释放。相反,对象本身应提供方法,其对已处置对象的含义将是清晰明确的。这些方法可能在内部使用 IsDisposed 标志,但必须使用任何必要的锁定来防止竞争条件。一般来说,模式

  如果(!myThing.isDisposed)
    myThing.DoSomething();

表示 myThing 应该真正支持 DoSomethingIfNotDisposed 方法(可能称为 TryDoSomething)。如果您不能这样做,我的倾向可能是编写您自己的 DoSomethingIfNotDisposed 扩展方法并使用 Try/Catch 来抑制 ObjectDisposedException(或对象将抛出的任何特定异常)。

于 2011-04-14T15:50:47.677 回答
1

在使用之前检查对象是否已处置。

仍然不是最好的设计模式。但是,这是我用来确定是否处置对象的方法。

if (!object.IsDisposed) object.DoSomething();

或者

public string DoSomething()
{
    if (this.IsDisposed) return null;
}

如果这不起作用,您可以尝试添加 IsDisposed 标志并覆盖 dispose 方法。并在您自己的代码中将其设置为 true。

于 2011-04-13T20:49:02.913 回答
1

继承你的类并添加属性:

class MyCancellationTokenSource: CancellationTokenSource
{
    public bool MyIsDisposed { get; private set; }
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        MyIsDisposed = true;
     }
}
于 2017-11-02T13:43:10.207 回答