Я пытаюсь написать метод, который обрабатывает некоторые сообщения.Их можно читать или писать сообщения.Параллельное чтение разрешено, но при получении блокировки write
все последующие блокировки чтения должны ждать, пока не будет снята блокировка записи.Так что я ReaderWriterLockSlim
это то, что мне нужно.Но когда я пытаюсь реализовать простое приложение, чтобы увидеть, работает ли оно должным образом, я получаю Recursive read lock acquisitions not allowed in this mode
исключение.
Вот мой пример, чтобы показать, как оно должно работать:
ReaderWriterLockSlim distributionLock = new ReaderWriterLockSlim();
async Task ExecuteReadLockTaskAsync(Func<Task> taskFunc)
{
distributionLock.EnterReadLock();
try
{
await taskFunc();
}
finally
{
if (distributionLock.IsReadLockHeld)
{
distributionLock.ExitReadLock();
}
}
}
async Task ExecuteWriteLockTaskAsync(Func<Task> taskFunc)
{
distributionLock.EnterWriteLock();
try
{
await taskFunc();
}
finally
{
if (distributionLock.IsWriteLockHeld)
{
distributionLock.ExitWriteLock();
}
}
}
Task ProcessAsync(bool flag)
{
switch (flag)
{
case false:
return ExecuteReadLockTaskAsync(() =>
{
Console.WriteLine("Readonly task start");
return Task.Delay(1000).ContinueWith(t => Console.WriteLine("Readonly task done"));
});
case true:
return ExecuteWriteLockTaskAsync(() =>
{
Console.WriteLine("Write task start");
return Task.Delay(3000).ContinueWith(t => Console.WriteLine("Write task done"));
});
default:
throw new InvalidOperationException($"Unknown message typex");
}
}
var tasks= new List<Task>();
for (int i = 0; i < 100; i++)
{
tasks.Add(ProcessAsync(false));
}
tasks.Add(ProcessAsync(true));
for (int i = 0; i < 100; i++)
{
tasks.Add(ProcessAsync(false));
}
await Task.WhenAll(tasks);
Ожидаемый результат: 100 строк Readonly task start
, одна строка Write task start
, затем 100 строк Readonly task done
, затем одна строка Write task done
, затем печатается остальная часть программы.
Фактический результат:
Readonly task start
Readonly task done
LockRecursionException4
Recursive read lock acquisitions not allowed in this mode.
Я не понимаю, где здесь появляется рекурсия.Я просто вызываю одну функцию без какой-либо рекурсии.Я читаю статьи, но не вижу, как это работает.