ReaderWriterLockSlim和async \ await
我有一些ReaderWriterLockSlim
问题。 我无法理解它是如何工作的。
我的代码:
private async Task LoadIndex() { if (!File.Exists(FileName + ".index.txt")) { return; } _indexLock.EnterWriteLock();// _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(); }
当我在输入写锁定时,在调试器中我可以看到_indexLock.IsWriteLockHeld
为true
,但是当执行步骤为时,我看到_indexLock.IsWriteLockHeld
为false
而_indexLock.ExitWriteLock
抛出exceptionSynchronizationLockException
并显示消息“The write锁被释放而没有被举行“。 我做错了什么?
ReaderWriterLockSlim
是一个线程仿射锁类型,因此它通常不能与async
和await
一起使用。
您应该将SemaphoreSlim
与WaitAsync
一起WaitAsync
,或者(如果您确实需要读取器/写入器锁定),请使用AsyncReaderWriterLock
的AsyncReaderWriterLock或Stephen Toub的AsyncReaderWriterLock
。
您可以使用可靠且轻量级的SemaphoreSlim
安全地模拟读取器/写入器锁定机制,并保留async
/ await
的优点。 创建SemaphoreSlim
,为其提供相当于锁定资源以便同时读取的例程数量的可用锁数。 每个人都会像往常一样请求一把锁。 对于您的编写例程,请确保在执行此操作之前请求所有可用的锁。
这样,您的编写例程将始终单独运行,而您的读取例程可能只在它们之间共享资源。
例如,假设您有2个读取例程和1个写入例程。
SemaphoreSlim semaphore = new SemaphoreSlim(2); async void Reader1() { await semaphore.WaitAsync(); try { // ... reading stuff ... } finally { semaphore.Release(); } } async void Reader2() { await semaphore.WaitAsync(); try { // ... reading other stuff ... } finally { semaphore.Release(); } } async void ExclusiveWriter() { // the exclusive writer must request all locks // to make sure the readers don't have any of them // (I wish we could specify the number of locks // instead of spamming multiple calls!) await semaphore.WaitAsync(); await semaphore.WaitAsync(); try { // ... writing stuff ... } finally { // release all locks here semaphore.Release(2); // (oh here we don't need multiple calls, how about that) } }
显然,只有当您事先知道可以同时运行多少个读取例程时,此方法才有效。 不可否认,他们中的太多会让这段代码变得非常丑陋。