2 回答
TA贡献1848条经验 获得超6个赞
正如指出的这个页面(部分更加深入地了解任务和任务<T>的CPU绑定的操作),任务从他们被称为线程上运行,而CPU限制的工作其实应该被包裹在一个Task.Run如此它”将在另一个(后台)线程上运行。所以,是的,在异步方法中使用 Task.Run 来进行 CPU 绑定或其他阻塞工作是正常且正常的。从页面引用:
public async Task<int> CalculateResult(InputData data)
{
// This queues up the work on the threadpool.
var expensiveResultTask = Task.Run(() => DoExpensiveCalculation(data));
// Note that at this point, you can do some other work concurrently,
// as CalculateResult() is still executing!
// Execution of CalculateResult is yielded here!
var result = await expensiveResultTask;
return result;
}
CalculateResult() 在调用它的线程上执行。当它调用 Task.Run 时,它会将昂贵的 CPU 绑定操作 DoExpensiveCalculation() 排入线程池并接收一个任务句柄。DoExpensiveCalculation() 最终在下一个可用线程上并发运行,可能在另一个 CPU 内核上。当 DoExpensiveCalculation() 忙于另一个线程时,可以进行并发工作,因为调用 CalculateResult() 的线程仍在执行。
一旦遇到 await,CalculateResult() 的执行就交给它的调用者,允许在 DoExpensiveCalculation() 生成结果时使用当前线程完成其他工作。完成后,结果将排队等待在主线程上运行。最终,主线程将返回执行CalculateResult(),此时它将得到DoExpensiveCalculation() 的结果。
TA贡献1877条经验 获得超1个赞
答案是:视情况而定。
您指出了调度程序,这正是问题所在。如果您在线程池(默认调度程序)上运行,那么运行同步的 CPU 密集型工作非常好。如果你在 UI 线程上运行,这可能会导致糟糕的用户体验。
也就是说,虽然这是一个问题,但这不是你的问题。您的合同已实施DoSomeStuff
,您将在当前调度程序上运行一些工作。由调用者决定这是否可能是一个问题,在这种情况下添加一个Task.Run
以抵消对另一个调度程序的调用。
简而言之,不要使用await Task.Run(() => DoCpuBoundWork());
. 让知道执行上下文的调用者为您决定。
- 2 回答
- 0 关注
- 176 浏览
添加回答
举报