Garantir l'exécution unique de l'initialisation asynchrone en C#
Cet article aborde le défi consistant à garantir que l'initialisation asynchrone d'une classe, via sa méthode InitializeAsync()
, ne s'exécute qu'une seule fois, même avec des appels simultanés de plusieurs threads.
Une approche utilise SemaphoreSlim
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <code class = "language-csharp" > 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);
});
}
}</code>
|
Copier après la connexion
Une solution plus élégante exploite AsyncLazy<T>
:
1 2 3 4 5 6 7 8 9 10 | <code class = "language-csharp" > public class AsyncLazy<T> : Lazy<Task<T>>
{
public AsyncLazy(Func<T> valueFactory) :
base(() => Task.Run(valueFactory)) { }
public AsyncLazy(Func<Task<T>> taskFactory) :
base(() => Task.Run(() => taskFactory())) { }
public TaskAwaiter<T> GetAwaiter() { return Value.GetAwaiter(); }
}</code>
|
Copier après la connexion
Exemple d'utilisation :
1 2 3 4 5 | <code class = "language-csharp" > private AsyncLazy<bool> asyncLazy = new AsyncLazy<bool>(async () =>
{
await DoStuffOnlyOnceAsync();
return true;
});</code>
|
Copier après la connexion
Remarque : un espace réservé booléen est utilisé car DoStuffOnlyOnceAsync()
n'a pas de type de retour.
Pour une implémentation AsyncLazy<T>
raffinée, référez-vous au billet de blog de Stephan Cleary : https://www.php.cn/link/366c0196895c9eeaa75992bacac60426
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!