我有一个IDisposable
对象,可以在多个线程之间访问。我试图找出一种方法来跟踪对象是否正在使用"在进行任何清理之前。换句话说,我需要保留某种引用计数来指示存在正在运行的方法(它们在完成时递减),以便Dispose方法不会继续直到它们全部完成(或者在一些超时之后)通过)。但我还需要确保在输入Dispose
之后,以后对Method
的任何调用都会失败。
类似的东西:
class MyObject : IDisposable
{
private long _counter;
private bool _stopping;
private IDisposable _someResource;
public void Method()
{
if (_stopping)
throw new InvalidOperationException();
Interlocked.Increment(ref _counter);
try
{
// do some work
}
finally
{
Interlocked.Decrement(ref _counter);
}
}
public void Dispose()
{
var timeout = DateTime.Now.Add(TimeSpan.FromSeconds(15));
while ( DateTime.Now < timeout && Volatile.Read(ref _counter) > 0)
{
// wait
// Thread.Sleep(10) or something
}
_stopping = true;
//perform clean up
_someResource.Dispose();
}
}
但是这不会起作用,因为Method()
可能会再次被调用而_stopping
尚未设置,但Dispose
会继续,其他所有内容都会失效。
我可以在这里使用特定的模式,还是可以用一些框架类来解决这个问题?基本上是一些双向信号告诉Dispose
没有任何事情正在进行中,因此它在向Method
发信号通知它应该失败的过程中表现良好。
我找到了CountdownEvent,但我不知道如何在这里使用它。 This answer显示示例CountdownLatch
,但它不会阻止请求新作品。
答案 0 :(得分:0)
没有。只要对Dispose方法负责&#34;追踪&#34;消耗该类的所有实例。班上的消费者需要处理他们的清理并妥善处理。
如果可以通过多个类多次调用Dispose,那么您只是发现了代码味道。只有一个班级应该调用处理方法;并且该类应该使用Dispose方法跟踪类的使用者。
防止多次调用dispose的常见模式是设置一个标志,类似于现在的标志。根据需要使用ObjectDisposedException:
private bool _zombified;
public void Method()
{
if (_zombified)
throw new ObjectDisposedException();
// method's logic
}
public void Dispose
{
if(_zombified)
{
return;
}
_zombified = true;
// perform clean-up
}