请考虑以下控制台应用程序:
public static void Request(string url)
{
ThreadPool.QueueUserWorkItem((state) =>
{
try
{
var request = WebRequest.Create(url);
request.Timeout = 5000;
request.GetResponse();
}
catch (Exception e)
{
Console.Out.WriteLine(e);
}
Console.Out.WriteLine(url);
});
}
static void Main(string[] args)
{
Request("http://google.com?q=a");
Request("http://google.com?q=b");
Request("http://google.com?q=c");
Request("http://google.com?q=d");
Thread.Sleep(20000);
Console.In.ReadLine();
}
输出将完成 2 个网址。但对于其余部分,它将抛出"操作已超时"。我知道默认情况下并行连接的限制设置为两个。如果我把它增加到三个,那么三个就会完成。即:
ServicePointManager.DefaultConnectionLimit = 3;
但我的问题是 - 为什么其余的没有完成,而是抛出操作超时了?
因为超时包括进程排队等待连接可用的时间。
超时表示"我想在调用GetResponse()
后最多等待 5000 毫秒以获得我的响应">,而不是"我想在等待无限时间后最多再等待 5000 GetResponse()
毫秒才能轮到队列"。
现在,您想知道,"但是查询太快了,完成时间应该不会超过 5000 毫秒!问题来自您没有关闭从 MSDN 的 GetResponse 获得的响应:
必须调用 Close 方法来关闭流并释放 连接。否则可能会导致应用程序用完 连接。
调用Dispose()
隐式调用Close()
,因此,如果您更新代码以释放响应,则使用的连接将被释放,然后其中一个等待请求将能够启动。
public static void Request(string url)
{
ThreadPool.QueueUserWorkItem((state) =>
{
try
{
var request = WebRequest.Create(url);
request.Timeout = 5000;
using(var response = request.GetResponse())
{
Console.Out.WriteLine("Response - " + url);
}
}
catch (Exception e)
{
Console.Out.WriteLine(e);
}
Console.Out.WriteLine("Method End - " + url);
});
}
static void Main(string[] args)
{
Request("http://google.com?q=a");
Request("http://google.com?q=b");
Request("http://google.com?q=c");
Request("http://google.com?q=d");
Thread.Sleep(20000);
Console.In.ReadLine();
}