tal*_*als 13 .net c# asynchronous task-parallel-library async-await
假设我有一个需要使用InitializeAsync()方法执行异步初始化的类.我想确保初始化只执行一次.如果另一个线程在初始化正在进行时调用此方法,它将"等待"直到第一个调用返回.
我正在考虑以下的实现(使用SemaphoreSlim).有更好/更简单的方法吗?
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);
});
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
编辑:
由于我正在使用DI并且将注入此服务,因此将其作为"懒惰"资源使用或使用异步工厂对我来说不起作用(尽管在其他用例中它可能很好).因此,异步初始化应该封装在类中,并对IMyService
消费者透明.
将初始化代码包装在"虚拟" AsyncLazy<>
对象中的想法将完成这项工作,尽管对我来说感觉有点不自然.
我会去AsyncLazy<T>
(略有修改版):
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(); }
}
Run Code Online (Sandbox Code Playgroud)
并像这样消耗它:
private AsyncLazy<bool> asyncLazy = new AsyncLazy<bool>(async () =>
{
await DoStuffOnlyOnceAsync()
return true;
});
Run Code Online (Sandbox Code Playgroud)
注意我bool
只是因为你没有返回类型而使用DoStuffOnlyOnceAsync
.
编辑:
斯蒂芬·克利里(当然)也有这方面的一个实现此.
是.使用Stephen ClearyAsyncLazy
(可在AsyncEx
nuget上获得):
private static readonly AsyncLazy<MyResource> myResource = new AsyncLazy<MyResource>(
async () =>
{
var ret = new MyResource();
await ret.InitAsync();
return ret;
}
);
public async Task UseResource()
{
MyResource resource = await myResource;
// ...
}
Run Code Online (Sandbox Code Playgroud)
或视觉工作室SDK的AsyncLazy
,如果你喜欢微软的实现.
通常,我更喜欢异步工厂方法,因为我认为它们更简单,更安全:
public class MyService
{
private MyService() { }
public static async Task<MyService> CreateAsync()
{
var result = new MyService();
result.Value = await ...;
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
AsyncLazy<T>
是定义共享异步资源的一种非常好的方法(并且可能是"服务"的更好的概念匹配,具体取决于它的使用方式).异步工厂方法方法的一个优点是无法创建未初始化的版本MyService
.
归档时间: |
|
查看次数: |
2301 次 |
最近记录: |