0

In a FileWriter class that will be used by different threads, I currently use a ReaderWriterLockSlim to prevent errors occurring when two threads try to write to the file at the same time like this:

(1)

public class FileWriter
{
    private ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim();

    public void WriteToFile(string message)
    {
        try
        {
            this.readerWriterLock.EnterWriteLock();    
            // the writing happens here
        }
        finally
        {
            this.readerWriterLockSlim.ExitWriteLock();
        }
    }
}

which does work. But after that, I read that ReaderWriterLockSlim implements IDisposable, and so I wondered whether

(2)

public class FileWriter
{
    public void WriteToFile(string message)
    {
        using (ReaderWriterLockSlim readerWriterLockSlim = new ReaderWriterLockSlim())
        {
            readerWriterLockSlim.EnterWriteLock();
            // the writing happens here
            readerWriterLockSlim.ExitWriteLock();
        }
    }
}

would be the "better" approach and whether it might introduce some new drawbacks. My gut feeling tells me that I probably shouldn't create a new ReaderWriterLockSlim every time the method is called but rather only once as in (2).

Sadly though, it does not work (it's as if I hadn't even used a lock) and so I figured that (2) can't be correct. But then again, why would ReaderWriterLockSlim implement IDisposable if it wasn't planned to be used as in (2)?


What is the correct usage of ReaderWriterLockSlim?

Thomas Flinkow
  • 4,845
  • 5
  • 29
  • 65

1 Answers1

7

Not every IDisposable is directly used in a using statement. The other pattern is if you have an IDisposable in one of your classes fields (and your class "owns" that object1), then your class should also implement IDisposable and clean up its disposables during Dispose.

You're correct that your re-write is wrong, since every caller is using a different lock object and so no exclusion is happening.

See Dispose Pattern:

DO implement the Basic Dispose Pattern on types containing instances of disposable types. See the Basic Dispose Pattern section for details on the basic pattern.


1Thanks to Dirk's comment for the important caveat. If you're in a situation where you're not trying to control an object's lifetime, it's not appropriate to Dispose of such objects

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
  • Thank you for the clarificiation. I didn't even know the part about classes having `IDisposable` members should themselves implement `IDisposable`. I will accept the answer as soon as SO will let me. – Thomas Flinkow Jun 08 '18 at 07:59
  • 2
    I'd like to point out that only classes that **own** disposable members should take care of disposing such resources. An example where the class should not dispose a disposable member would be the case of dependency injection. – Dirk Jun 08 '18 at 08:09