【发布时间】:2015-12-10 12:48:26
【问题描述】:
场景
我需要在网页上显示 N 个报告。需要向外部服务请求报告。服务生成报告的时间可能从 2 秒到 50 秒不等,具体取决于请求的内容。
为了调用服务,我在 async 操作中使用 HttpClient。为了生成 1 份报告,我调用了一次服务。为了生成 5 个报告,我调用了 5 次,以此类推。
问题
假设我们请求 3 个报告 BigReport、MediumReport 和 SmallReport,已知相对生成时间分别为 1 分 30 秒和 2 秒,我们调用该服务以下顺序:
大报告、中报告、小报告
HttpCalls 的结果如下:
- BigReport 的 HttpCall 响应返回 SmallReport(生成速度最快)
- MediumReport 将是正确的
- SmallReport 响应将包含 BigReport(最长也是最后一个)
基本上,虽然 HttpCalls 是不同的,但由于它们是在很短的时间内发出的,而且它们仍然“活跃”,服务器将根据 先到先得的方式进行响应,而不是为每个呼叫提供确切的响应。
守则
我有一个带有如下异步操作的请求控制器:
public async Task<string> GenerateReport(string blockContent)
{
var formDataContent = new MultipartFormDataContent
{
AddStringContent(userid, "userid"),
AddStringContent(passcode, "passcode"),
AddStringContent(outputtype, "outputtype"),
AddStringContent(submit, "submit")
};
var blockStream = new StreamContent(new MemoryStream(Encoding.Default.GetBytes(blockContent)));
blockStream.Headers.Add("Content-Disposition", "form-data; name=\"file\"; filename=\"" + filename + "\"");
formDataContent.Add(blockStream);
using (var client = new HttpClient())
{
using(var message = await client.PostAsync(Url, formDataContent))
{
var report = await message.Content.ReadAsStringAsync();
return report;
}
}
}
正在通过 Ajax 从视图调用操作,如下所示
//FOREACH BLOCK, CALL THE REPORT SERVICE
$('.block').each(function(index, block) {
var reportActionUrl = "Report/GenerateReport/"+block.Content;
//AJAX CALL GetReportAction
$(block).load(reportActionUrl);
});
如果我通过删除异步任务而不是“等待”响应,将操作从异步转换为同步,一切正常,我只是得到结果
var result = client.PostAsync(Url, formDataContent).Result.
这将使一切同步运行并正常工作,但用户的等待时间会更长。我真的很想通过并行调用或类似方法来避免这种情况。
结论和问题
问题本身是有道理的,在使用 Fiddler 进行检查后,我们几乎同时有多个打开的 HttpRequests 待处理。 我想我需要一种 handler 或 something 来识别和匹配请求/响应,但我不知道我需要查看的“域”的名称是什么为了。到目前为止,我的问题是:
- “并行进行多个http调用”的技术名称是什么?
- 如果问题是可以理解的,那么问题的名称是什么? (并发、并行请求排队等?)
- 当然,有什么解决办法吗?
非常感谢。
【问题讨论】:
-
通常,无论您使用同步还是异步 IO,调用都应该是并行的。它们是并行的,因为请求是独立的,并且没有任何东西将它们序列化。你怎么知道请求不是并行处理的?您的 Fiddler 测试似乎正好相反。
-
或者是响应混淆的问题?在这种情况下,您调用的报告服务已损坏。贴出它的代码。使用 Fiddler 确保它返回错误的结果。
-
问题是响应混淆了。 Fiddler 清楚地显示了这个问题。那么你认为这不是正常的行为吗?然后,如果我删除异步行为,就会出现一种“死锁”,应用程序会等待第一次调用完全完成,然后再开始第二次调用。这样做的响应不会不匹配。我希望这是有道理的。
-
什么系统混淆了响应?我知道这里有两种服务。
-
你能写出 $reportBlock.load 的样子吗?它在做什么,它是如何发出 ajax 请求和填充数据的?
标签: c# asp.net-mvc asynchronous async-await dotnet-httpclient