Search code examples
c#.netmultithreading.net-coreeventstoredb

Synchronise access to singleton object initialisation


I'm accessing an EventStore from a dotnet core web application. There is a single connection shared by all threads. The connection is opened on first access and I need to ensure only one thread opens the connection. Previously I would have used a lock but then I can't await the method to open the connection.

I found the following snippet of code that looks like it should do the trick:

public class AsyncLock : IDisposable
{
    private readonly SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(1, 1);

    public async Task<AsyncLock> LockAsync()
    {
        await _semaphoreSlim.WaitAsync().ConfigureAwait(false);
        return this;
    }

    public void Dispose()
    {
        _semaphoreSlim.Release();
    }
}

And use it in my code:

private static readonly AsyncLock _mutex = new AsyncLock();
private volatile bool _isConnected = false;
private async Task EstablishConnected()
{
    if (!_isConnected)
    {
        using (await _mutex.LockAsync())
        {
            if (!_isConnected)
            {
                await _connection.ConnectAsync().ConfigureAwait(false);
                _isConnected = true;
            }
        }
    }
}

Is this a reasonable approach to synchronising access to initialise/open the connection to the EventStore?


Solution

  • Turns out there is a useful nuget library and associated Github repo from Stephen Cleary that is a drop in replacement for the AsyncLock class above.