**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