비동기에서[async/await] lock 사용하기

SemaphoreSlim 클래스를 사용하면 비동기에서 lock을 사용할 수 있다.

 

 

AsyncLock.cs 

namespace Common;

public sealed class AsyncLock
{
    // 한번에 하나의 스레드만 접근 가능하도록 설정되어, 사실상 뮤텍스처럼 동작한다. 
    private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);

    // 동시 실행 제한 수 3
    //private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(3); 

    public async Task<IDisposable> LockAsync()
    {
        await _semaphore.WaitAsync();
        return new Handler(_semaphore);
    }

    private sealed class Handler : IDisposable
    {
        private readonly SemaphoreSlim _semaphore;
        private bool _disposed = false;

        public Handler(SemaphoreSlim semaphore)
        {
            _semaphore = semaphore;
        }

        public void Dispose()
        {
            if (_disposed == false)
            {
                _semaphore.Release();
                _disposed = true;
            }
        }
    }
}

 

 

사용 방법 ↓

private readonly AsyncLock _AsyncLock = new AsyncLock();

public async Task TestAsyncLock()
{
    using (await _AsyncLock.LockAsync())
    {
        await 뭔가 작업 
    }
}

 

IDisposable을 상속받는 Handler 클래스로 처리하기 때문에 별도의 관리가 필요 없다.

 

 

 

참고)

https://jacking75.github.io/csharp_asyncawait_lock/