c# - throttle 异步任务?

标签 c# .net asynchronous async-await throttling

我想知道如果要完成的任务数量很大,我们是否应该限制异步任务。假设您有 1000 个 URL,您是否一次触发所有请求并等待所有请求:

var tasks = urlList.Select(url => downloadAsync(url));
await Task.WhenAll(tasks);

或者您对请求进行批处理并一批接一批地处理:

foreach (var urlBatch in urlList.BatchEnumerable(BatchSize)){
    var tasks = urlBatch.Select(url => downloadAsync(url));
    await Task.WhenAll(tasks);
}

我认为批处理不是必需的,因为第一种方法(一次触发所有请求)将创建由 ThreadPool 调度的任务,所以我们应该让 ThreadPool 决定何时执行每个任务。但是,有人告诉我,实际上只有当任务是计算任务时才有效。当任务涉及网络请求时,第一种方法可能导致主机挂起 ???这是为什么?

最佳答案

在大多数情况下,您想限制自己做某事。当您同时运行多个操作时,您总是会在某处保存一些状态。如果它们受 CPU 限制,那么任务将存储在等待线程的 ThreadPool 队列中,如果它是异步的,那么状态机就位于堆上。

即使是异步操作也通常会占用一些有限的资源,例如带宽、端口、远程数据库服务器的 CPU 等。

不过,您不必将自己一次限制为一个批处理(因为您需要等待最后一个操作完成,而不是开始其他操作)。您可以使用 SlimSemahpore 或更好的 TPL Dataflow block 进行 throttle :

var block = new ActionBlock<string>(
   url => downloadAsync(url),
   new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 10 });    

urlList.ForEach(url => block.Post(url));

block.Complete();
await block.Completion;

关于c# - throttle 异步任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35023685/

相关文章:

c# - 使用 .Net6 显示来自 Azure Blob 的图像数组

c# - LINQ 查询将列表中的几个项目变为选中状态

.net - 如何使用值转换器将字节数组绑定(bind)到 WPF 中的图像?

c# - WPF - DataGrid 中记录插入的自定义验证规则

c# - 在 C# 中合并包含列表的字典

c# - 如何设置另一个应用程序焦点并使其成为事件窗口

c# - System.Net.Mail无法加载或初始化请求的服务提供者

javascript - 如何在 FormDataConsumer 中使用异步 javascript 函数(例如 fetch)

javascript - Ember : Resolve complex async promises

node.js - promise 中的 fs.writeFile,异步同步的东西