【发布时间】:2016-12-02 17:28:45
【问题描述】:
我有一个异步方法,GetExpensiveThing(),它执行一些昂贵的 I/O 工作。我就是这样使用它的:
// Serial execution
public async Task<List<Thing>> GetThings()
{
var first = await GetExpensiveThing();
var second = await GetExpensiveThing();
return new List<Thing>() { first, second };
}
但由于这是一种昂贵的方法,我想并行执行这些调用。我原以为移动 awaits 会解决这个问题:
// Serial execution
public async Task<List<Thing>> GetThings()
{
var first = GetExpensiveThing();
var second = GetExpensiveThing();
return new List<Thing>() { await first, await second };
}
这不起作用,所以我将它们包装在一些任务中,这有效:
// Parallel execution
public async Task<List<Thing>> GetThings()
{
var first = Task.Run(() =>
{
return GetExpensiveThing();
});
var second = Task.Run(() =>
{
return GetExpensiveThing();
});
return new List<Thing>() { first.Result, second.Result };
}
我什至尝试在任务中和任务周围使用 await 和 async,但它真的很混乱,我没有运气。
是否有更好的并行运行异步方法,或者任务是一种好方法?
【问题讨论】:
-
@bside 你歪曲了链接的帖子。它正确地指出
async函数中的延续是在捕获的上下文中安排的。但在大多数情况下,该上下文是默认的SynchronizationContext,它将继续调度到线程池中,从而使它们并行运行。即使在 WPF 和 ASP 应用程序中,您也可以使用ConfigureAwait(false)解决它。Task.Run与 CPU 绑定任务一起使用,您不需要它来并行运行延续。 -
@V0ldek 是的,你是对的。感谢您引起我的注意。
标签: c# async-await task-parallel-library