如何发现一个对象已处理

本文关键字:一个对象 处理 发现 何发现 | 更新日期: 2023-09-27 17:50:12

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

CancellationTokenSource已被释放。

如何在使用对象之前发现该对象已被处理?

如何发现一个对象已处理

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

在任何情况下,如果一个线程拉出其他线程所依赖的数据结构和对象,那么就不要这样做。修复您的代码,让这些对象在需要时保持活动状态。

换句话说,在处理CancellationTokenSource之前,请等待其他线程完成对它的需求

一些一次性对象的创建者应该稍微违反微软的"规则",即对已处理的对象执行任何操作都应该引发异常,而应该遵循更通用的规则,即在无法满足方法的后期条件时,应该引发异常。如果Cancel方法的目的是确保没有人会继续将作业视为活动,并且即使在调用Cancel方法之前,每个人都将该作业视为已死亡,则无论对象是否已处理,都会满足该方法的发布条件。

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

if(!myThing.isDisposed(myThing.DSomething((;

表示myThing应该真正支持DoSomethingIfNotDisposed方法(可能称为TryDoSometing(。如果你不能做到这一点,我可能倾向于编写你自己的DoSomethingIfNotDisposed扩展方法,并使用Try/Catch来扼杀ObjectDisposedException(或对象会抛出的任何特定异常(。

继承您的类并添加属性:

class MyCancellationTokenSource: CancellationTokenSource
{
    public bool MyIsDisposed { get; private set; }
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        MyIsDisposed = true;
     }
}

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

仍然不是最好的设计模式。然而,以下是我用来确定对象是否被处理的方法。

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

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

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

我同意Lasse V.Karlsen的观点。然而,如果你想要它:

bool IsDisposed = true;
var privateInt = tokenSource?.GetType().GetProperty("IsDisposed", 
BindingFlags.Instance | BindingFlags.NonPublic);
if (privateInt != null)
{
   IsDisposed = (bool)privateInt.GetValue(tokenSource);
}