在构造函数中执行任务 [重复]
Posted
技术标签:
【中文标题】在构造函数中执行任务 [重复]【英文标题】:Executing a Task inside of a constructor [duplicate] 【发布时间】:2020-07-15 17:06:44 【问题描述】:我一直在尝试为您的类型具有依赖关系并且您想要调用返回Task
的方法的情况找到一种设计。直觉反应是做GetAwaiter().GetResult()
,但我知道这违背了异步任务的全部目的。想法是启动任务,但让它做它的事情,直到类型需要它。
public class SomeClass
private readonly Task<Data> _getDataTask;
private readonly IDependency _dep;
private Data _data;
public SomeClass(IDependency dep)
_dep = dep;
// I'll spin this up but I don't need the result yet
_getDataTask = _dep.GetDataAsync();
public async Task DoSomeWork()
// Now I need the result of the task so I'll await the task
_data = await _getDataTask;
ExecuteWorkOn(_data);
如果您没有缓存结果,也许这种方法会产生很多条件语句等待?我希望获得有关这种方法的反馈,希望可以链接另一个 SO 问题,或者我们提出以前没有考虑过的设计。
更新 1
我将Task
设为Task<Data>
,如其中一个cmets 中所述
【问题讨论】:
这种方法没有错 如果没有人打电话给DoSomeWork
,那么GetDataAsync
的电话是不是就浪费了?如果是这样,您似乎可以在这里使用Lazy
来推迟拨打电话,直到需要。
不应该_getDataTask
是Task<T>
?
@Damien_The_Unbeliever 我在 Stephen Cleary 的博客上读到了关于自定义构建的 AsyncLazy这个问题有两个很好的解决方案:
第一:
在构造函数中使用异步初始化方法并将生成的Task
保存在属性中。这样调用代码可以等待初始化完成。
public class Foo
public Task InitTask get; private set;
public Foo()
this.InitTask = this.Init();
private async Task Init() ...
可以这样使用
var newFoo = new Foo();
await newFoo.InitTask();
// can now use newFoo
第二:
使用仅使用的私有构造函数并拥有一个 Create
方法,您可以使用它为您的类创建实例
public class Foo
public Foo()
public async Task<Foo> Create()
var newFoo = new Foo();
await newFoo.Init();
return newFoo;
private async Task Init() ...
可以这样使用
var newFoo = await Foo.Create();
您的方法(如果不错的话)是方法 1 的变体,但这意味着您需要在每个需要任务结果(或副作用)的方法中等待构造函数中启动的任务。
public class Foo
private Task InitTask get; private set;
public Foo()
this.InitTask = this.Init();
private async Task Init() ...
public async Task DoStuffA()
await this.InitTask;
// do work
public async Task DoStuffB()
await this.InitTask;
// do work
public async Task DoStuffC()
await this.InitTask;
// do work that could be done without async/await
所以我建议使用方法 2 进行异步初始化。
【讨论】:
在我的工作中,我确实经常使用构建器模式来构建不可变类型。也许构建器的异步版本会按照您await builder.BuildAsync()
的顺序排列。我想知道 AsyncLazyawait
之前不要获取它。以上是关于在构造函数中执行任务 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin 协程协程取消 ③ ( finally 释放协程资源 | 使用 use 函数执行 Closeable 对象释放资源操作 | 构造无法取消的协程任务 | 构造超时取消的协程任务 )
Kotlin 协程协程取消 ③ ( finally 释放协程资源 | 使用 use 函数执行 Closeable 对象释放资源操作 | 构造无法取消的协程任务 | 构造超时取消的协程任务 )