WebRequest 在从并行线程启动时注定要失败



请考虑以下控制台应用程序:

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();
}

最新更新