Скажем, у меня есть класс, который должен выполнить некоторую инициализацию async, используя метод InitializeAsync(). Я хочу убедиться, что инициализация выполняется только один раз. Если другой поток вызывает этот метод, пока инициализация уже выполняется, он будет "ждать", пока не вернется первый вызов.
Я думал о следующем: (с помощью SemaphoreSlim). Есть ли лучший/более простой подход?
public class MyService : IMyService
{
private readonly SemaphoreSlim mSemaphore = new SemaphoreSlim(1, 1);
private bool mIsInitialized;
public async Task InitializeAsync()
{
if (!mIsInitialized)
{
await mSemaphore.WaitAsync();
if (!mIsInitialized)
{
await DoStuffOnlyOnceAsync();
mIsInitialized = true;
}
mSemaphore.Release();
}
}
private Task DoStuffOnlyOnceAsync()
{
return Task.Run(() =>
{
Thread.Sleep(10000);
});
}
}
Спасибо!
Edit:
Поскольку я использую DI, и эта услуга будет введена, ее использование как "Lazy" ресурса или использование async factory не будет работать для меня (хотя это может быть здорово в других случаях использования).
Таким образом, инициализация async должна быть инкапсулирована внутри класса и прозрачна для потребителей IMyService
.
Идея обернуть код инициализации в объекте "dummy" AsyncLazy<>
будет выполнять эту работу, хотя для меня это немного неестественно.