ただ1つのAsyncLockを持つ代わりに、完全な辞書を作成してください。メッセージキーは、辞書内のAsyncLockのキーです。一度に1つのキー処理を持つメッセージが1つだけであれば、ブロックされることはありません。私はさらにあなたのメッセージキーが文字列であると仮定しています。
private readonly Dictionary<string, AsyncLock> _mutexes = new Dictionary<string, AsyncLock>();
private AsyncLock GetMutex(string key)
{
lock (_mutexes)
{
AsyncLock mutex;
if (!_mutexes.TryGetValue(key, out mutex))
{
// no mutex yet, create a new one
mutex = new AsyncLock();
_mutexes.Add(key, mutex);
}
return mutex;
}
}
....
protected async Task Process(Message msg)
{
using (await GetMutex(msg.Key).LockAsync())
{
...
}
}
キーのミューテックスが既に存在する場合、すべての可能性にGetMutex方法は、さらに、例えば、ロック操作を避けるために最適化することができることに注意してください最初にContainsKeyでチェックし、そうでない場合はロックして追加します。しかし、その最適化が100%スレッドセーフであるかどうかはわかりませんので、ここには含めませんでした。
JasonのConcurrentDictionaryのコメントに触発されて、私はGetMutexのConcurrentDictionaryバージョンのコードを提供することに決めました。私は、スレッドセーフではない辞書へのアクセスを最適化することについて、私が上に述べたことを試してみることはお勧めしません。
ConcurrentDictionary<string, AsyncLock> _mutexes = new ConcurrentDictionary<string, AsyncLock>();
private AsyncLock GetMutexes(string key)
{
return _mutexes.GetOrAdd(key, s => { return new AsyncLock(); });
}
「キー」はどのようなタイプですか?それが文字列でない場合、 'lock'ステートメントで動作する可能性があります。 –
はい、それは文字列です – Rikard