保證 C# 中非同步初始化的單次執行
本文解決了透過其 InitializeAsync()
方法確保類別的非同步初始化僅執行一次的挑戰,即使來自多個執行緒的並發呼叫也是如此。
一個方法使用 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#中如何保證非同步初始化的單次執行?的詳細內容。更多資訊請關注PHP中文網其他相關文章!