Last active
January 21, 2022 10:36
-
-
Save 0x49D1/a28eac0c17272c36184f8c4b39c9cc3b to your computer and use it in GitHub Desktop.
Locking mechanics with named locks for async operations. After finishing lock code block this code releases semaphore itself. Standard "lock" statement can't be used with async operations: https://stackoverflow.com/a/7612714/47672
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Usage example: | |
// static readonly SemaphoreLocker _semaphoreLocker = new SemaphoreLocker(); | |
// var values = await _semaphoreLocker.LockAsync(valuesKey, async () => { return await SomeActionAsync(); }); | |
public class SemaphoreLocker | |
{ | |
static readonly ConcurrentDictionary<string, SemaphoreSlim> lockDictionary = new ConcurrentDictionary<string, SemaphoreSlim>(); | |
public async Task LockAsync(string key, Func<Task> worker) | |
{ | |
SemaphoreSlim semaphore = lockDictionary.GetOrAdd(key, new SemaphoreSlim(1, 1)); | |
await semaphore.WaitAsync(); | |
try | |
{ | |
await worker(); | |
} | |
finally | |
{ | |
semaphore.Release(); | |
lockDictionary.TryRemove(key, out semaphore); | |
} | |
} | |
// Overloading variant for non-void methods with return type (generic T) | |
public async Task<T> LockAsync<T>(string key, Func<Task<T>> worker) | |
{ | |
SemaphoreSlim semaphore = lockDictionary.GetOrAdd(key, new SemaphoreSlim(1, 1)); | |
await semaphore.WaitAsync(); | |
try | |
{ | |
return await worker(); | |
} | |
finally | |
{ | |
semaphore.Release(); | |
lockDictionary.TryRemove(key, out semaphore); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment