从并行线程开始,WebRequest注定要失败

时间:2014-10-10 16:51:21

标签: c# .net

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

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个网址。但对于其余部分,它将抛出“操作已经超时”。 我知道默认情况下并行连接的限制设置为2。如果我将它增加到3,那么三个将完成。 即:

ServicePointManager.DefaultConnectionLimit = 3;

但我的问题是 - 为什么其余的人没有完成,但投掷操作已经超时了?

1 个答案:

答案 0 :(得分:3)

因为超时包括进程排队等待连接可用的时间。

代表&#34的超时时间我打电话给GetResponse()以获得我的回复" 不是"我想要等待最多5000毫秒在GetResponse()等待无限量的时间在队列中轮流后,最多等待5000毫秒。"

现在,你想知道,"但是查询非常快,完成时间不应超过5000毫秒!"。问题来自于您没有关闭GetResponse的响应,from the MSDN:

  

您必须调用Close方法关闭流并释放   连接。如果不这样做可能会导致您的申请用完   连接。

调用Dispose()隐式调用Close(),因此如果您更新代码以处理您的响应,那么已使用的连接将被释放,其中一个等待请求将能够启动。 / p>

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