【发布时间】:2019-04-17 15:34:06
【问题描述】:
我正在向一个 API 发送大约 100,000 个 JSON 对象的列表,该 API 只能一个一个地接受它们,并且我正在异步发送它们。我知道 API 在内部将接收到的对象发送到一个队列,该队列似乎被所有这些请求阻塞,这导致我在其中一些请求之后收到“网关超时”错误。
我尝试将列表拆分成不同大小的批次,并在发送每个批次后使线程进入睡眠状态,但最终发生的情况是它在批次大小时出现相同的错误,我已经尝试过3000、2500 和 1000 批次,结果相同,线程似乎永远不会休眠。
这是有问题的代码:
public async Task TransferData(IEnumerable<MyData> data)
{
var pages = Math.Ceil(data.Count() / 3000m);
for (var page = 0; page < pages; page++)
{
await TransferPage(data.Skip(page * 3000).Take(3000);
Thread.Sleep(10000);
}
}
private async Task TransferPage(IEnumerable<MyData> data)
{
await Task.WhenAll(data.Select(p => webConnection.PostDataAsync(JsonConvert.SerializeObject(p, Formatting.None))));
}
注意:webConnection 只是一个已经实例化了 HttpClient 的类,并对预期 URL 的数据执行 PostAsync。
对 TransferData 的调用是在控制台应用程序中完成的,如下所示:
try
{
...
dataManager.TransferData(data).Wait();
}
catch(AggregateException ex)
{
...
}
catch(Exception ex)
{
...
}
感谢您的指导。
更新:澄清一些在 cmets 中出现的混淆。外部 API 正在一一接收对象,如果您查看 WhenAll 内部的私有方法 TransferPage,IEnumerable 有一个 Select,其中调用了内部执行实际 HttpClient PostAsync 的方法.因此,对象被分批分组,并且在每批中它们被一个接一个地发送。我希望这能让它更清楚一点。
【问题讨论】:
-
如果只能按顺序处理,为什么要并行发送?
-
您需要等待
Task.Delay。不要将 Thread.Sleep 与 async-await 混合使用。您也不要将 async-await 与.Wait()之类的阻塞调用混合使用,因为这会导致死锁 -
正如@slaks 所说,帖子中的代码和文本不对齐 - 正如代码所示,“一个接一个”和 3000 个批次之间存在显着差异。
-
所以你必须在线程睡眠之前使用 await Task.Delay() 也你缺少 ')"。但问题是你试图同时发送大量数据而不是一个一个地发送。跨度>
-
SemaphoreSlim的情况。见link。
标签: c# async-await dotnet-httpclient