I have some problems with ReaderWriterLockSlim
. I cannot understand how it's magic working.
My code:
private async Task LoadIndex()
{
if (!File.Exists(FileName + ".index.txt"))
{
return;
}
_indexLock.EnterWriteLock();// <1>
_index.Clear();
using (TextReader index = File.OpenText(FileName + ".index.txt"))
{
string s;
while (null != (s = await index.ReadLineAsync()))
{
var ss = s.Split(':');
_index.Add(ss[0], Convert.ToInt64(ss[1]));
}
}
_indexLock.ExitWriteLock();<2>
}
When I enter write lock at <1>, in debugger I can see that _indexLock.IsWriteLockHeld
is true
, but when execution steps to <2> I see _indexLock.IsWriteLockHeld
is false
and _indexLock.ExitWriteLock
throws an exception SynchronizationLockException
with message "The write lock is being released without being held". What I doing wrong?
You can safely emulate a reader/writer locking mechanism using the reliable and lightweight
SemaphoreSlim
and keep the benefits ofasync
/await
. Create theSemaphoreSlim
giving it the number of available locks equivalent to the number of routines that will lock your resource for reading simultaneously. Each one will request one lock as usual. For your writing routine, make sure it requests all the available locks before doing its thing.That way, your writing routine will always run alone while your reading routines might share the resource only between themselves.
For example, suppose you have 2 reading routines and 1 writing routine.
Obviously this method only works if you know beforehand how many reading routines you could have running at the same time. Admittedly, too much of them would make this code very ugly.
ReaderWriterLockSlim
is a thread-affine lock type, so it usually cannot be used withasync
andawait
.You should either use
SemaphoreSlim
withWaitAsync
, or (if you really need a reader/writer lock), use myAsyncReaderWriterLock
from AsyncEx or Stephen Toub'sAsyncReaderWriterLock
.