Dire che ho una classe che deve eseguire l'inizializzazione async usando un metodo InitializeAsync(). Voglio assicurarmi che l'inizializzazione venga eseguita solo una volta. Se un altro thread chiama questo metodo mentre l'initalizzazione è già in corso, si "attende" fino a quando non viene restituita la prima chiamata.Applicare un metodo asincrono per essere chiamato una volta
Stavo pensando alla seguente implementazione (utilizzando SemaphoreSlim). Esiste un approccio migliore/più semplice?
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);
});
}
}
Grazie!
Edit:
Dal momento che sto usando DI e questo servizio sarà iniettato, consumando come una risorsa "pigro" o utilizzando una fabbrica asincrona non funziona per me (anche se potrebbe essere grande in altri casi d'uso). Pertanto, l'inizializzazione asincrona dovrebbe essere incapsulata all'interno della classe e trasparente per i consumatori IMyService
.
L'idea di avvolgere il codice di inizializzazione in un oggetto "fittizio" AsyncLazy<>
farà il lavoro, anche se mi sembra un po 'innaturale.
Utilizzare un 'Lazy' il cui metodo di inizializzazione fa ciò che si desidera. Ciò garantisce che il metodo di inizializzazione venga chiamato solo una volta –
Se si utilizza questa soluzione, assicurarsi di chiamare "Rilascio" in un blocco finale. –