我有一个C#桌面应用程序,它需要同时向同一个Web服务器发出多个http请求。这是我为检查我的请求是否确实同时发生而进行的测试:
在Web服务器上,创建一个休眠3秒的测试页(模拟一些长时间运行的任务),然后返回当前日期/时间。这是代码(VB.Net):
<%system.threading.thread.sleep(3000)%GT;<%=现在%GT;
在C#app中,我有一个函数MakeRequest(),它使用System.Net.Http.HttpClient发出Web请求,并以字符串形式返回响应。
然后在C#app中有一个按钮点击调用的函数,它异步调用MakeRequest()多次:
var responses = await Task.WhenAll(MakeRequest(),MakeRequest(),MakeRequest());
在上面的例子中,MakeRequest()被调用3次。当我监视请求/秒性能计数器时,我在Web服务器上看到的是,它获得2个请求,然后3秒后再增加1个请求。这是设计的,因为System.Net.ServicePointManager.DefaultConnectionLimit的默认值是2,所以我的C#app一次只能发送2个请求,虽然我要求3. C#app完成按钮点击的总时间是6秒。
现在在C#应用程序中,我设置了ServicePointManager.DefaultConnectionLimit = 1000000.此时Web服务器上的Requests / sec显示3,并且C#应用程序中的按钮单击在3秒内完成。到目前为止一切都很好。
接下来,我将C#应用更改为同时进行60次呼叫,而不是3次。这就是事情变得有趣的地方。当我点击按钮时,我希望Web服务器上的Requests / sec能够达到60,而C#app会在3秒内完成按钮点击。我得到的是网络服务器请求/秒显示类似5,3秒后5等等,直到所有60个请求都已完成。当我再次单击该按钮时,相同的图片除了Requests / sec spike to 10或15之外,按钮点击显然更快完成。再次单击 - 此时请求/秒显示两个尖峰到30,按钮单击在6秒内完成。随后的按钮点击导致请求/秒尖峰首先到40然后到20(总共60个请求),然后是50和10,然后是55和5,最终我的C#应用程序开始一次性发送所有60个请求。按钮单击在3秒内完成,Web服务器上的请求/秒显示一个峰值为60.如果我继续按下按钮,我将始终同时收到所有60个请求。
但这不是全部。如果我停止按下按钮,我的C#应用程序似乎“忘记”它是以前的成就。我没有重新启动应用程序,只是停止按下按钮一会儿,然后在下一次按下时我一次又回到5个请求,如果我继续按下按钮,上面的情况会重复。
我还从MVC执行了上述测试 - 只是将代码从C#app复制并粘贴到MVC页面。得到了完全相同的结果。
任何人都可以解释一下发生了什么吗?谢谢
这是C#应用程序的代码。它是一个WinForms应用程序,代码存在于Form类中:
<!-- language: lang-c# -->
private HttpClient _httpClient = new HttpClient();
private async void button1_Click(object sender, EventArgs e)
{
ServicePointManager.DefaultConnectionLimit = 1000000;
var sw = Stopwatch.StartNew();
var responses = await Task.WhenAll(MakeRequest(), MakeRequest(), MakeRequest());
sw.Stop();
var msg = String.Join("\r\n", responses) + "\r\n\r\nTime Elapsed: " + sw.ElapsedMilliseconds;
MessageBox.Show(msg);
}
private async Task<string> MakeRequest()
{
using (var message = await _httpClient.GetAsync("http://TestServer/TestPage.aspx"))
{
return await message.Content.ReadAsStringAsync();
}
}
答案 0 :(得分:1)
有两个原因: