【发布时间】:2020-09-16 05:14:25
【问题描述】:
简短版:
任何人都可以确认,带有 EF 调用的非异步子函数上的 Task.Run/Task.WaitAll 对 ASP.NET 应用程序有什么好处吗?
长版:
我们有一个 Asp.Net WebApi 服务,该服务具有一个方法,该方法进行多个 DB 调用(全部使用 EntityFramework)来收集一组数据,这些数据全部返回到单个响应对象中。我们将其分解为一系列子函数,并希望它们并行运行(注意:这些函数都不使用任何异步调用)。
为了实现某种形式的并行编码,我们使用 Task.Run 调用每个函数,然后是 Task.WaitAll:
public ResponseObject PopulateResponseObject(int id)
{
var response = new ResponseObject();
Task<DataSetA> dataSetATask = Task.Run(() => getDataSetA(id));
Task<DataSetB> dataSetBTask = Task.Run(() => getDataSetB(id));
Task.WaitAll(dataSetATask, dataSetBTask);
response.SetA = dataSetATask.Result;
response.SetB = dataSetBTask.Result;
return response;
}
从我一直在阅读的内容来看,Task.Run 在 Asp.Net 应用程序中可能不会获得太多收益,而我们这里的内容可能只会导致不必要的线程池开销。
我们这样写代码是不是在浪费时间?
更新: 我们熟悉 EF 具有异步版本的事实,但是需要修改大量代码。我们希望保持这些功能不变。
【问题讨论】:
-
您可以只使用
Parallel.ForEach重载之一来节省一些麻烦 -
这取决于使用模式。如果你有一个相对很少调用的端点,你可能会提高性能(尤其是在一些长时间运行的东西的情况下),但总的来说 seems 不值得麻烦。
-
这将使用比需要更多的线程。创建
async-await是为了节省线程使用量。 EF 有异步 API。 -
@Marie - 好建议。我刚刚实现了一个 Parallel.Invoke 版本并正在对其进行测试。
-
当系统处于负载状态时,无法判断并行运行这些是否会产生任何好处。如果您正在处理来自许多用户的请求,线程很容易成为稀缺资源,您最终可能会等待一个可用。由于并发锁,您可能还会遇到线程之间的阻塞。判断是否有整体效益的唯一方法是模拟预期负载并查看系统如何响应。另请参阅race your horses。
标签: c# asp.net async-await task