我从dotnet核心网络应用程序访问EventStore。所有线程共享一个连接。首次访问时打开连接,我需要确保只有一个线程打开连接。以前我会使用lock
,但我无法await
方法打开连接。
我发现following snippet的代码看起来应该可以解决这个问题:
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的连接吗?
答案 0 :(得分:2)
原来,nuget library中有一个有用的Github repo和关联的Stephen Cleary,它代替了上面的AsyncLock
类。
答案 1 :(得分:1)
我认为你的方法是合理的。但是,如果您正在寻找管理初始化的异步方法,请查看Microsoft.VisualStudio.Threading包中可用的一些对象,例如AsyncLazy
。我不认为该软件包可用于.NET核心,但source code在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();
}
}