I have an IDisposable
object that can be accessed between multiple threads. I am trying to figure out a way to track that the object is "in use" before performing any clean up. In other words, I need to keep some sort of reference count to indicate that there are running methods (which are decremented when they complete) so that the Dispose method wouldn't continue until they are all complete (or after some timeout has passed). But I also need to make sure that once Dispose
has been entered that any future calls to Method
fail.
Something like:
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();
}
}
However this won't work because Method()
may be called again and _stopping
hasn't been set but the Dispose
would continue, invalidating everything else.
Is there a specific pattern that I can use here or perhaps some framework classes that can be used to solve this? Basically some two-way signal telling Dispose
that nothing is in process so its good-to-go while signalling Method
that it should fail.
I found CountdownEvent but I'm not sure how I can use it here. This answer shows an example CountdownLatch
but it doesn't prevent new work from being requested.