C# での非同期初期化の単一実行の保証
この記事では、複数のスレッドからの同時呼び出しであっても、InitializeAsync()
メソッドを介したクラスの非同期初期化が 1 回だけ実行されるようにするという課題に取り組みます。
1 つのアプローチでは、SemaphoreSlim
:
<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>
より洗練されたソリューションは AsyncLazy<T>
を利用します:
<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>
使用例:
<code class="language-csharp">private AsyncLazy<bool> asyncLazy = new AsyncLazy<bool>(async () => { await DoStuffOnlyOnceAsync(); return true; });</code>
注: DoStuffOnlyOnceAsync()
には戻り値の型がないため、ブール型のプレースホルダーが使用されます。
洗練された AsyncLazy<T>
実装については、Stephan Cleary のブログ投稿を参照してください: https://www.php.cn/link/366c0196895c9eeaa75992bacac60426
以上がC# で非同期初期化を確実に 1 回実行するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。