1

我正在从 dotnet 核心 Web 应用程序访问EventStore 。所有线程共享一个连接。连接在第一次访问时打开,我需要确保只有一个线程打开连接。以前我会使用 alock但后来我无法await打开连接。

我发现下面的代码片段看起来应该可以解决问题:

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();
    }
}

并在我的代码中使用它:

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;
            }
        }
    }
}

这是同步访问以初始化/打开与 EventStore 的连接的合理方法吗?

4

2 回答 2

2

原来有一个有用的nuget 库和来自Stephen Cleary的相关Github存储库,它是上述类的替代品。AsyncLock

于 2018-02-08T21:39:30.410 回答
1

我认为你的方法是合理的。但是,如果您正在寻找管理初始化的异步方法,请查看 Microsoft.VisualStudio.Threading 包中的一些可用对象,例如AsyncLazy. 我不认为该软件包可用于 .NET 核心,但源代码在 github 上并在 MIT 许可下。

使用 AsyncLazy,您可以执行以下操作:

public class MyEventStoreConsumer
{
    private static readonly Func<Task<IEventStoreConnection>> getConnection;

    static MyEventStoreConsumer()
    {
        var eventStore = EventStoreConnection.Create(...);
        var connection = new AsyncLazy<IEventStoreConnection>(async () =>
        {
            await eventStore.ConnectAsync().ConfigureAwait(false);
            return eventStore;
        });
        getConnection = () => connection.GetValueAsync();
    }
}
于 2018-02-08T21:43:25.617 回答