2010-06-05 171 views
0

当从不同的线程调用不同的URL时,HttpWebRequest.GetResponse方法的性能非常差。 例如,如果我们有一个线程并执行url1,则需要3秒。 如果我们在parallet中执行url1和url2,它需要10秒,第一个请求在8秒后结束,在10秒后结束第二个请求。HttpWebRequest.GetResponse在多线程应用程序中的性能问题

如果我们exutet 10个URL url1,url2,... url0它需要1分4秒!!!第一个请求在50秒后结束!

我使用GetResponse方法。 我试过了DefaultConnectionLimit但它没有帮助。 如果使用BeginGetRequest/EndGetResponse方法,它的工作速度非常快,但前提是从一个线程调用此方法。如果来自不同,它也是非常缓慢的。 我需要一次执行多个线程的Http请求。

在每个线程中执行相同的代码。如果只有一个线程的GetResponse方法工作得非常快。 对于每个线程,URL中的IP addreses也不相同。 如果您编译并运行以下代码,您将看到请求逐个处理。拳头执行3秒,第二次8秒,第三次15秒.... 即从多线程没有收益。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Net; 
using System.IO; 
using System.Xml; 
using System.Reflection; 
using System.Threading; 
using System.Collections.Generic; 
using System.Collections.Specialized; 
using System.Collections; 

namespace HttpRequestExample 
{ 

    class HttpPerformer 
    { 
     private Thread thread = null; 
     HttpWebRequest httpRequest = null; 

     public void start(string url) 
     { 
      thread = new Thread(new ThreadStart(WorkerThread)); 
      thread.Name = url; 
      thread.Start(); 

     } 

     public void WorkerThread() 
     { 
      try 
      { 
       HttpWebRequest req = (HttpWebRequest)WebRequest.Create((string)thread.Name); 
       Console.WriteLine(DateTime.Now + " : before get response " + thread.Name); 
       HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); 
       Console.WriteLine(DateTime.Now + " : after get response " + thread.Name); 

      } 
      catch (Exception e) 
      { 
       Console.WriteLine(DateTime.Now + " : Exception : " + e.Message + thread.Name); 
      } 
     } 
    } 

    class HttpAccessUtils 
    { 
     public static bool SetAllowUnsafeHeaderParsing20() 
     { 
      //Get the assembly that contains the internal class 
      Assembly aNetAssembly = Assembly.GetAssembly(typeof(System.Net.Configuration.SettingsSection)); 
      if (aNetAssembly != null) 
      { 
       //Use the assembly in order to get the internal type for the internal class 
       Type aSettingsType = aNetAssembly.GetType("System.Net.Configuration.SettingsSectionInternal"); 
       if (aSettingsType != null) 
       { 
        //Use the internal static property to get an instance of the internal settings class. 
        //If the static instance isn't created allready the property will create it for us. 
        object anInstance = aSettingsType.InvokeMember("Section", 
        BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.NonPublic, null, null, new object[] { }); 

        if (anInstance != null) 
        { 
         //Locate the private bool field that tells the framework is unsafe header parsing should be allowed or not 
         FieldInfo aUseUnsafeHeaderParsing = aSettingsType.GetField("useUnsafeHeaderParsing", BindingFlags.NonPublic | BindingFlags.Instance); 
         if (aUseUnsafeHeaderParsing != null) 
         { 
          aUseUnsafeHeaderParsing.SetValue(anInstance, true); 
          return true; 
         } 
        } 
       } 
      } 
      return false; 
     } 
    } 

    class Program 
    { 

     static void Main(string[] args) 
     { 
      HttpAccessUtils.SetAllowUnsafeHeaderParsing20(); 
      ServicePointManager.UseNagleAlgorithm = true; 
      ServicePointManager.Expect100Continue = true; 
      ServicePointManager.CheckCertificateRevocationList = true; 
      ServicePointManager.DefaultConnectionLimit = 200; //ServicePointManager.DefaultPersistentConnectionLimit; 
      ServicePointManager.MaxServicePoints = 100; 
      Console.WriteLine(ServicePointManager.MaxServicePoints); 


      ArrayList a = new ArrayList(150); 

      for (int i = 100; i < 220; i++) 
      { 
       a.Add("http://207.242.7." + i.ToString()); 
      } 

      for (int i = 0; i < a.Count; i++) 
      { 
       HttpPerformer hp = new HttpPerformer(); 
       hp.start((string)a[i]); 
      } 

     } 

     static void performRequest(object url) 
     { 
      try 
      { 
       HttpWebRequest req = (HttpWebRequest)WebRequest.Create((string)url); 
       Console.WriteLine(DateTime.Now + " : before get response " + url); 
       HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); 
       Console.WriteLine(DateTime.Now + " : after get response " + url); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(DateTime.Now + " : Exception : " + e.Message + (string)url); 
      } 

     } 
    } 
} 

有没有人遇到过这样的问题?谢谢你的任何建议。

+0

添加到帖子 – Nikita 2010-06-05 20:21:37

+0

的代码你可以发布有问题的_your_代码吗?并且你发布的代码甚至不会编译,因为你错过了一个'('。 – Oded 2010-06-05 20:22:00

+0

邮政编码,它会在我们的机器上重现问题。如有必要,使用文件共享服务。 – 2010-06-05 20:29:37

回答

1

您需要在获取响应流后关闭conn,否则连接将长时间保持打开状态。这可能是缓慢的原因。

0

您需要在获得响应后关闭连接。这似乎会导致问题。