**This is just an extension to [this answer][1].**
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<Task> worker)
{
await _semaphore.WaitAsync();
try
{
await worker();
}
finally
{
_semaphore.Release();
}
}
// overloading variant for non-void methods with return type (generic T)
public async Task<T> LockAsync<T>(Func<Task<T>> worker)
{
await _semaphore.WaitAsync();
T result = default;
try
{
result = await worker();
}
finally
{
_semaphore.Release();
}
return result;
}
}
**Usage:**
public class Test
{
private static readonly SemaphoreLocker _locker = new SemaphoreLocker();
public async Task DoTest()
{
await _locker.LockAsync(async () =>
{
// [async] calls can be used within this block
// to handle a resource by one thread.
});
// OR
var result = await _locker.LockAsync(async () =>
{
// [async] calls can be used within this block
// to handle a resource by one thread.
}
}
}
[1]: https://stackoverflow.com/questions/7612602/why-cant-i-use-the-await-operator-within-the-body-of-a-lock-statement/18257065#18257065