并行执行多个 Web 请求和响应解析的高效策略

Efficient strategy to do Multiple Webrequests and Response parsing in parralel

我的服务有一个函数可以触发网络请求、解析响应并使用响应进行大量计算以最终给出一个集合。

我现在必须对这些进行多次调用以获得许多集合,这些集合可以在以后聚合成一个。我想我可以选择其中任何一个 Parrallel.ForEach and Tasks.StartNew

您能否建议哪种方法可以有效地处理具有 Web 请求处理和计算的这种情况。

你也可以使用Task.WhenAll():

    ...
    List<int> list = new List<int> { 1, 2, 3 };
                var listTaks = list.Select(
                            async e => await DoOne(e)
                        );
                var results = await Task.WhenAll(listTaks);
    ...

更多信息在 Task.WhenAll Method

Parrallel.ForEachTasks.StartNew 用于 CPU 绑定的工作负载。对于 I/O-bound 工作负载,您需要异步性,这是由 Task.Run(async () => { await ... 最方便地提供的。现在,在您的情况下,您同时拥有 CPU 和 I/O 绑定工作负载。好消息是异步基础设施也能很好地处理 CPU 绑定的工作负载。例如,这是完全有效的:

private async void Button1_Click(object sender, EventArgs args)
{
    var webData = await GetWebData(url); // I/O bound
    var parsedList = await Task.Run(() => ParseWebData(webData)); // CPU bound
    await SaveListToDB(parsedList); // I/O bound
}

在 I/O 操作期间不会阻塞任何线程,线程池线程将执行 CPU 密集解析。从可伸缩性和资源保护的角度来看,没有比这更好的了。但是,如果您愿意占用计算机的所有资源以获得最佳性能,不为其他进程留出任何空闲时间,那么您的策略应该是让所有 processors/cores 始终处于忙碌状态,而在同时执行外部世界可以处理的最大并发 I/O 操作数(网络服务器、文件系统、数据库,都对同时可以完成的工作量有限制)。

用于实施此策略的一个好工具是 TPL Dataflow library, build-in for .NET Core and available as a package for .NET Framework。如果您对此一无所知,它有一些学习曲线,但不是很陡峭。经过 2-3 天的学习后,您会非常有信心用它编写出高质量且健壮的生产代码。它拥有拆分、加入、转换、缓冲和并行化工作负载所需的所有工具,让您感觉自己在控制流程,而无需微观管理一切。