2014-02-20 58 views
4

我构建此方法(c#)以接收来自URL的HTTP响应状态代码。 当我运行这个方法,它的工作正常,但是当我在一个循环中运行它,第三次卡住了。任何线索?HttpWebResponse在循环中运行时卡住

public static string isAlive(string url) 
    { 
     Console.WriteLine("start: Is Alive Test"); 
     WebRequest request = WebRequest.Create(url); 
     try 
     { 
      HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
      return Convert.ToString((int)response.StatusCode); 
     } 
     catch(WebException ex) 
     { 
      HttpWebResponse res = (HttpWebResponse)ex.Response; 
      return Convert.ToString((int)res.StatusCode); 
     } 
    } 

循环

 for (int i = 0; i < 5; i++) 
     { 
      string a = isAlive("https://www.yahoo.com/"); 
      Console.WriteLine(a); 
     } 
+0

你确定它卡住,而不仅仅是等待响应?服务器很可能会限制请求,因为它可能检测到可疑活动(在如此短的时间内向服务器投掷如此多的请求可能会成为DoS攻击)。鉴于您希望在不阻塞UI线程的情况下发出大量请求,您可能需要考虑改为使用“BeginX”/“EndX”调用。 – James

+0

定义'卡住'。如果你的程序在三次尝试后挂起,可能是雅虎服务器拒绝你的快速连续的https请求。另一种选择是您的操作系统阻止快速连接到相同的地址(内部防洪)。编辑 - 答案是另一种选择,你有太多的连接一次打开。 –

+0

您需要将.GetResponse()封装到'using'语句中,并使您的isAlive方法异步以进行性能考虑。看到我的代码示例如下。 –

回答

8

你不是HttpWebResponse对象,这意味着连接仍然躺在附近的调用Dispose。如果你改变你的代码如下:

public static string isAlive(string url) 
{ 
    Console.WriteLine("start: Is Alive Test"); 
    WebRequest request = WebRequest.Create(url); 
    try 
    { 
     using(HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
     { 
      return Convert.ToString((int)response.StatusCode); 
     } 

    } 
    catch(WebException ex) 
    { 
     using(HttpWebResponse res = (HttpWebResponse)ex.Response) 
     { 
      return Convert.ToString((int)res.StatusCode); 
     } 
    } 
} 

using声明将隐式调用Dispose对你来说,这将关闭连接。

你的代码在第二次迭代后停止的原因是因为.Net有一个内置的最大连接数,它将打开一个网站,这是默认的2.这是由System.Net.ServicePointManager.DefaultConnectionLimit控制,你可以增加,如果你需要。

+0

我认为你必须为'ex.Response'做同样的事情。 –

+0

虽然我同意他们应该用'使用'来包装这个,但我怀疑这是问题的原因。响应对象一旦超出了“isAlive”调用的范围,它就会被释放(尽管并非即刻)。这也不会影响随后的呼叫。 – James

+0

@詹姆斯假设你让应用程序有足够的时间让垃圾收集器在每次迭代后清理。 –

0

它可能与您不关闭HttpWebResponse有关。 添加一个finally来关闭响应的try catch。 也关闭catch中的WebException响应。

0

使用“使用”,它会运作良好。

 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
     { 
      return Convert.ToString((int)response.StatusCode); 
     } 
0
  • 你需要用HttpWebResponse VAR为using声明,因为它是一次性
  • 检查前ex.Response.StatusCode确保ex.Status是ProtocolError
  • 而且还考虑对你的方法异步出于性能考虑,
  • 由于您的方法正在返回一个状态代码,因此它可能会有一个比这更好的名称,因为它是活动的

样品:

public static async Task<string> GetStatusCode(string url) 
{ 
    var request = (HttpWebRequest)WebRequest.Create(url); 

    try 
    { 
     using (var response = (HttpWebResponse)await request.GetResponseAsync()) 
     { 
      return response.StatusCode.ToString(); 
     } 
    } 
    catch (WebException ex) 
    { 
     return ex.Status == WebExceptionStatus.ProtocolError ? 
       ((HttpWebResponse)e.Response).StatusCode.ToString() : null; 
    } 
}