【发布时间】:2020-07-03 11:34:37
【问题描述】:
我有一个类需要很长时间才能启动,因为它在构造函数中执行了一些长时间运行的操作。 我需要创建 3 个这样的对象并将它们添加到字典中。
我正在尝试使用 async,以便创建 3 个线程,每个线程启动其中一个对象,但发现它有点混乱。
最初我以为我会等到所有线程都完成后,然后将结果添加到字典中,但是我无法编译代码,所以我求助于做字典。在线程中添加(这样可以吗?)
我写了以下代码
public void CreateAccountStuffs(ICollection<Account> accounts)
{
CreateStuff(accounts);
}
private async void CreateStuff(ICollection<Account> accounts)
{
var tasks = accounts.Select(a => CreateStuffForAccount(a));
await Task.WhenAll(tasks);
}
private Task CreateStuffForAccount(Account account)
{
//Long Running process due to website calls in AccountWrapper construction
var accountWrapper = new AccountWrapper(account);
return Task.FromResult(accountWrapper);
}
最后一行似乎毫无意义,但没有它我无法编译代码。我觉得我在这里遗漏了一些非常明显的东西,但是我的多线程技能太生疏了,我很难看到什么。
我的直觉是,有一种更简单的方法来编写我需要做的事情,但我不知道那是什么。
例如我注意到this question 似乎建议您可以编写一个返回 Task 的方法,并简单地在方法主体中编写返回“This String”,但是,该构造不会为我编译。我得到错误无法从字符串转换为任务
注意 - 已编辑以删除不属于问题的代码 - 之前涉及 2 个构造函数,这使事情变得混乱 - 这是 AccountWrapper 中长期运行的构造函数。
【问题讨论】:
-
您没有任何异步代码。简单地用
async标记方法不会使其异步。您可以与Task.Run(() => ....并行运行非异步代码 -
您需要以异步方式执行长时间运行的任务,但这在构造函数中是不可能的。也许这为你清除了一些问题:stackoverflow.com/questions/23048285/… 或者这个:blog.stephencleary.com/2013/01/async-oop-2-constructors.html
-
@Homungus 第二个很有用谢谢 - 我将重构使用那里建议的模式,看看我最终会在哪里。
-
我已经重构 AccountWrapper 类以使用工厂构造函数 public static Task
CreateAsync(Account account) 但是,现在在调用代码中,如果我尝试访问 AccountWrapper - 它会告诉我它无法从 Task 转换为 AccountWrapper,我应该使用 await,但如果我将 await 放入此代码中,那么我也需要使其异步!
标签: c# asynchronous task