如何发现一个对象已处理
本文关键字:一个对象 处理 发现 何发现 | 更新日期: 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);
}