Как и было предложено, используйте TPL Dataflow.
Возможно, вы TransformBlock
.
Вы определяете MaxDegreeOfParallelism
для ограничения того, сколько строк может быть преобразовано (т. е. сколько URL-адресов может быть загружено) параллельно. Затем вы отправляете URL-адреса блоку, и когда вы закончите, вы сообщите блоку, что вы закончили добавление элементов, и вы получите ответы.
var downloader = new TransformBlock(
url => Download(url),
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 50 }
);
var buffer = new BufferBlock();
downloader.LinkTo(buffer);
foreach(var url in urls)
downloader.Post(url);
//or await downloader.SendAsync(url);
downloader.Complete();
await downloader.Completion;
IList responses;
if (buffer.TryReceiveAll(out responses))
{
//process responses
}
Примечание. Буферы TransformBlock
как его ввод, так и вывод. Почему тогда нам нужно связать его с BufferBlock
?
Поскольку TransformBlock
не будет завершена до тех пор, пока все элементы (HttpResponse
) не будут использованы, а await downloader.Completion
будет висеть , Вместо этого мы позволяем downloader
перенаправлять весь свой вывод на выделенный буферный блок - тогда мы ждем завершения downloader
и проверяем буферный блок.