using System; using System.Threading; using System.Threading.Tasks; public class SemaphoreLocker { private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); public async Task LockAsync(Func worker) { var isTaken = false; try { do { try { } finally { isTaken = await _semaphore.WaitAsync(TimeSpan.FromSeconds(1)); } } while (!isTaken); await worker(); } finally { if (isTaken) { _semaphore.Release(); } } } // overloading variant for non-void methods with return type (generic T) public async Task LockAsync(Func> worker) { var isTaken = false; try { do { try { } finally { isTaken = await _semaphore.WaitAsync(TimeSpan.FromSeconds(1)); } } while (!isTaken); return await worker(); } finally { if (isTaken) { _semaphore.Release(); } } } }