gpt4 book ai didi

c# - 只初始化一次异步模式

转载 作者:行者123 更新时间:2023-11-30 14:55:03 29 4
gpt4 key购买 nike

假设我有一个类,其成员需要异步操作来初始化(例如文件 i/o 或 Web 请求)。我只需要初始化一次,我不想重新初始化。

Tasks 和 Async-Await 是否适合完成此任务?

这是我目前正在做的一个例子:

private Task _initializeTask;
public Task InitializeAsync()
{
return _initializeTask ?? (_initializeTask = Task.Run(
async () =>
{
// Do an action requiring await here
await _storageField.LoadAsync();
}));
}

这是否符合我的预期?有更好的方法吗?

它是线程安全的吗?不是必需的,但应该考虑。

编辑:

我认为它的作用是什么? 我相信如果 _initializeTask 没有被分配,那么它将被分配一个新任务,该任务将启动,然后等待其中包含的异步 lambda。对该方法的任何后续调用都将等待分配给 _initializedTask 的已经运行(或完成)的任务。

我希望它什么时候构建? 通常,我会在使用 IoC 容器解析的服务上使用这种方法。可以使用对类的引用来构造多个依赖类。然后,在使用之前,它们中的每一个都等待 InitializeAsync()。如果有多个依赖类,那么我不想在初始化它时加倍努力。

工厂方法? 通常不会构造多个需要初始化的实例,因此工厂方法似乎不是一个好的解决方案。对于文件夹包装器类之类的东西,我使用了类似“静态 CreateAsync()” 的方法,但这并没有让我将初始化的文件夹注入(inject)构造函数。当异步工厂方法不能与 IoC 构造函数注入(inject)一起使用时,它们不会获得任何好处。

最佳答案

您的代码可以工作,但它不是线程安全的,_initializeTask检查null后可以更改并在初始化之前。这将导致两次初始化。我会考虑使用 AsyncLazy<T> ,它继承自 Lazy<T>这是线程安全的。

然后假设 LoadAsync返回 Task而不是 Task<T> ,您的代码变为(未经测试):

private AsyncLazy<object> initializeTask = new AsyncLazy<object>(async () =>
{
// Do an action requiring await here
await _storageField.LoadAsync();
return null;
});

public Task InitializeAsync()
{
return _initializeTask.Value;
}

您还可以定义一个非通用版本的 `AsyncLazy,这样您就不必从初始化例程中返回一个值。

public class AsyncLazy : Lazy<Task> 
{
public AsyncLazy(Func<Task> taskFactory) :
base(() => Task.Run(taskFactory)) { }
}

然后您可以使用初始化方法对其进行初始化,但是编译器要求该方法是静态的:

private AsyncLazy _initializeTask = new AsyncLazy(LoadStorageAsync);

private static async Task LoadStorageAsync()
{
// Do an action requiring await here
await _storageField.LoadAsync();
}

public Task InitializeAsync()
{
return _initializeTask.Value;
}

关于c# - 只初始化一次异步模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26268870/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com