いくつかのメッセージを処理するメソッドを作成しようとしています。それらはメッセージの読み取りまたは書き込みです。並列読み取りは許可されますが、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
が 1 行Write task start
、次に が 100 行Readonly task done
、次に が 1 行Write task done
、残りのプログラムが出力されます。
実結果:
Readonly task start
Readonly task done
LockRecursionException4
Recursive read lock acquisitions not allowed in this mode.
ここで再帰がどこに現れるのかわかりません。再帰を一切行わずに、1 つの関数を呼び出しているだけです。記事を読みましたが、ここでどのように機能するかわかりません。