保证 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中文网其他相关文章!