2010-06-02 12 views
58

Estoy desarrollando una aplicación (winforms C# .NET 4.0) donde accedo a una funcionalidad de búsqueda de un tercero a través de una simple solicitud HTTP. Llamo a una url con un parámetro, y a cambio obtengo una pequeña cadena con el resultado de la búsqueda. Suficientemente simple.Intentando ejecutar varias solicitudes HTTP en paralelo, pero estando limitado por Windows (registro)

El reto es, sin embargo, que tengo que hacer muchas de estas búsquedas (un par de miles), y me gustaría limitar el tiempo necesario. Por lo tanto, me gustaría ejecutar solicitudes en paralelo (digamos 10-20). Yo uso un ThreadPool a hacer esto, y la versión corta de mi código tiene este aspecto:

public void startAsyncLookup(Action<LookupResult> returnLookupResult) 
{ 
    this.returnLookupResult = returnLookupResult; 

    foreach (string number in numbersToLookup) 
    { 
     ThreadPool.QueueUserWorkItem(lookupNumber, number); 
    } 
} 

public void lookupNumber(Object threadContext) 
{ 
    string numberToLookup = (string)threadContext; 
    string url = @"http://some.url.com/?number=" + numberToLookup; 
    WebClient webClient = new WebClient(); 
    Stream responseData = webClient.OpenRead(url); 
    LookupResult lookupResult = parseLookupResult(responseData); 

    returnLookupResult(lookupResult); 
} 

cumplo numbersToLookup (un List<String>) de otro lugar, llame startAsyncLookup y dotarla de una función de devolución de llamada returnLookupResult para devolver cada resultado Esto funciona, pero descubrí que no obtengo el rendimiento que quiero.

Inicialmente pensé que podría ser la tercera parte tener un sistema pobre en su extremo, pero lo excluí tratando de ejecutar el mismo código desde dos máquinas diferentes al mismo tiempo. Cada uno de los dos tomó tanto tiempo como uno solo, por lo que podría descartar ese.

Un colega me indicó que esto podría ser una limitación en Windows. Busqué en Google un poco, y encontré entre otros this post diciendo que de forma predeterminada Windows limita el número de solicitudes simultáneas al mismo servidor web a 4 para HTTP 1.0 y a 2 para HTTP 1.1 (para HTTP 1.1 esto está de acuerdo con la especificación (RFC2068))).

La misma publicación mencionada anteriormente también proporcionó una forma de aumentar estos límites. Al agregar dos valores de registro a [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings] (MaxConnectionsPerServer y MaxConnectionsPer1_0Server), pude controlarlo yo mismo.

Así que probé esto (me senté a 20), reinicié mi computadora y traté de ejecutar mi programa nuevamente. Lamentablemente, no pareció ayudar a ninguno. También estuve atento al Resource Monitor (see screen shot) mientras ejecutaba mi búsqueda por lotes, y noté que mi aplicación (la que tenía el título bloqueado) aún solo usaba dos conexiones TCP.

Entonces, la pregunta es, ¿por qué no funciona? ¿La publicación a la que me he vinculado usa los valores de registro incorrectos? ¿Es posible que ya no sea posible "piratear" en Windows (estoy en Windows 7)?

Cualquier idea sería muy apreciada :)

Y por si alguien debería preguntarse, también he intentado con diferentes ajustes para MaxThreads en ThreadPool (everyting de 10 a 100), y esto no parecía afectar mi rendimiento en absoluto, por lo que el problema no debería estar allí tampoco.

+0

enlace pantalla está dando Error HTTP 404 :( – RBT

+0

, sabemos por qué hay dos claves FEATURE_MAXCONNECTIONSPERSERVER y FEATURE_MAXCONNECTIONSPER1_0SERVER? ¿Cuál es el significado de estas dos teclas separadas? Lógicamente debería haber habido una sola. – RBT

+0

posterior Vinculado (pctools.com) ya no existe. – faintsignal

Respuesta

92

Es la materia de ServicePoint. Que proporciona administración de conexión para conexiones HTTP. El número máximo predeterminado de conexiones simultáneas permitidas por un objeto ServicePoint es 2. Si necesita aumentarlo, puede usar la propiedad ServicePointManager.DefaultConnectionLimit. Simplemente verifique el enlace en MSDN allí puede ver una muestra. Y establece el valor que necesitas

+1

Gracias, gracias, gracias :) ¡Eso fue todo! – Nailuj

+0

Bienvenido;). Me alegro de que ayude. – Incognito

+0

Gracias a ambos por una gran pregunta y respuesta – kape123

0

Para Internet Explorer 8: Ejecutar el Editor del Registro y vaya a siguiente clave HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Internet Explorer \ Main \ FeatureControl \ FEATURE_MAXCONNECTION SPERSERVER

y

HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Internet Explorer \ MAIN \ FeatureControl \ FEATURE_MAXCONNECTION SPER1_0SERVER

Si faltan FEATURE_MAXCONNECTIONSPERSERVER y FEATURE_MAXCONNECTIONSPER1_0SERVER, créelos. Ahora cree el valor DWORD llamado iexplore.exe para las dos claves secundarias (enumeradas anteriormente) y establezca su valor en 10 o en el número que desee.

+0

No puedo entender por qué esto funcionaría, ya que esto limita los límites para IE, y no en general ... Anywho, la respuesta de Incognito resolvió mi problema. – Nailuj

+0

No debería ser iexplore. exe pero el nombre del ejecutable de proceso y el límite solo se aplica a las conexiones que salen del control WebBrowser. –

27

Para una referencia más rápida para alguien. Para aumentar el límite de conexión por host, puede hacer esto en su Main() o en cualquier momento antes de comenzar a hacer las solicitudes HTTP.

System.Net.ServicePointManager.DefaultConnectionLimit = 1000; //or some other number > 4 
2

Dispara y olvida este método desde tu método principal. El usuario de Icognito es correcto, solo se permiten 2 hilos para jugar al mismo tiempo.

private static void openServicePoint() 
{ 
    ServicePointManager.UseNagleAlgorithm = true; 
    ServicePointManager.Expect100Continue = true; 
    ServicePointManager.CheckCertificateRevocationList = true; 
    ServicePointManager.DefaultConnectionLimit = 10000; 
    Uri MS = new Uri("http://My awesome web site"); 
    ServicePoint servicePoint = ServicePointManager.FindServicePoint(MS); 
} 
Cuestiones relacionadas