Я реализую простой загрузчик данных через HTTP, следуя советам из моего предыдущего вопроса C # .NET Операция параллельного ввода-вывода (с регулированием) , на которую отвечает Регулирование асинхронных задач .
Я разделяю загрузку и десериализацию, предполагая, что один может быть медленнее / быстрее другого. Также я хочу ограничить загрузку, но не хочу ограничивать десериализацию. Поэтому я использую два блока и один буфер.
К сожалению, я сталкиваюсь с проблемой, что этот конвейер иногда обрабатывает меньше сообщений, чем потребляется (я знаю от целевого сервера, что я выполнил ровно n
запросов, но в итоге получаю меньше ответов).
Мой метод выглядит следующим образом (без обработки ошибок):
public async Task<IEnumerable<DummyData>> LoadAsync(IEnumerable<Uri> uris)
{
IList<DummyData> result;
using (var client = new HttpClient())
{
var buffer = new BufferBlock<DummyData>();
var downloader = new TransformBlock<Uri, string>(
async u => await client.GetStringAsync(u),
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = _maxParallelism });
var deserializer =
new TransformBlock<string, DummyData>(
s => JsonConvert.DeserializeObject<DummyData>(s),
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded });
var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
downloader.LinkTo(deserializer, linkOptions);
deserializer.LinkTo(buffer, linkOptions);
foreach (Uri uri in uris)
{
await downloader.SendAsync(uri);
}
downloader.Complete();
await downloader.Completion;
buffer.TryReceiveAll(out result);
}
return result;
}
Если говорить точнее, у меня есть 100 URL для загрузки, но я получаю 90-99 ответов. Нет ошибок и сервер обработал 100 запросов. Это происходит случайным образом, большая часть кода времени ведет себя правильно.