I have a library with an API much like this:
public class Library : IDisposable
{
public Library(Action callback);
public string Query();
public void Dispose();
}
After I have instantiated Library, at any time and on any thread it might invoke the callback I have passed to it. That callback needs to call Query to do useful work. The library will only stop calling my callback once disposed, but if a callback attempts to call Query after the main thread has called Dispose, bad stuff will happen.
I do want to allow the callbacks to run on multiple threads simultaneously. That's okay. But we need to be sure that no callbacks can be running when we call Dispose. I thought a ReaderWriterLockSlim might be appropriate - you need the write-lock to call Dispose, and the callbacks need read-locks to call Query. The problem here is that ReaderWriterLockSlim is IDisposable, and I don't think it will ever be safe to dispose it - I can never know that there is not a callback in flight that simply hasn't gotten to the point of acquiring the read-lock yet.
What should I do? It looks like ReaderWriterLock isn't IDisposable, but it's own documentation says you should use ReaderWriterLockSlim instead. I could try to do something equivalent with just the "lock" keyword, but that sounds wasteful and easy to screw up.
PS - Feel free to say that the library API is not good if you think that's the case. I would personally prefer that it guaranteed that Dispose would block until all callbacks had completed.