nodo modificar manejo leer example especifico crear archivo c# parallel-processing webclient parallel.foreach downloadstring

manejo - leer y modificar xml c#



C#Descargar datos de la enorme lista de URL (4)

Esta pregunta ya tiene una respuesta aquí:

Tengo una gran lista de páginas web que muestran un estado, que debo verificar. Algunas URL están dentro del mismo sitio, otro conjunto está ubicado en otro sitio.

En este momento estoy tratando de hacer esto de forma paralela utilizando código como a continuación, pero tengo la sensación de que estoy causando demasiada sobrecarga.

while(ListOfUrls.Count > 0){ Parallel.ForEach(ListOfUrls, url => { WebClient webClient = new WebClient(); webClient.DownloadString(url); ... run my checks here.. }); ListOfUrls = GetNewUrls..... }

¿Se puede hacer esto con menos sobrecarga y un poco más de control sobre cuántos clientes y conexiones web uso / vuelvo a usar? Entonces, ¿al final el trabajo puede hacerse más rápido?


¿Pensaste en la ejecución asincrónica de tu código? Creo que no hay una forma más rápida de obtener datos de Internet, pero puedes hacerlo de forma simultánea.


Un elemento que a menudo se pasa por alto en los archivos web.config o app.config de su aplicación es la etiqueta connectionManagement. En particular, .NET limitará la cantidad simultánea de conexiones a un dominio a 2 por defecto. Puede ver la documentación de la etiqueta aquí .

Si entendí su pregunta correctamente, es lógico que los clientes web de creación paralela a 2 dominios estarán limitados a 4 subprocesos por defecto (2 subprocesos por dominio), causando menos aceleración de la que esperaría de otra manera.

Sin embargo, si se está conectando a varios dominios, es probable que las otras respuestas produzcan más aceleración, ya que esperar en la respuesta es probablemente una gran parte del costo de cada iteración de bucle. Si estás en .NET 4.5, el método GetStringAsync es probablemente tu amigo.


puede intentar utilizar HttpClient una nueva adición en .Net 4.5 que considere ser más rápido y podría mejorar un poco su rendimiento

using (HttpClient client = new HttpClient()) using (HttpResponseMessage response = await client.GetAsync(url)) using (HttpContent content = response.Content) { string result = await content.ReadAsStringAsync(); }


Parallel.ForEach es bueno para las tareas de cómputo vinculadas a la CPU, pero no será necesario bloquear los subprocesos de grupo para las llamadas sincrónicas vinculadas a IO como DownloadString en su caso. Puede mejorar la escalabilidad de su código y reducir el número de subprocesos que puede usar, utilizando DownloadStringTaskAsync y tareas en su lugar:

// non-blocking async method async Task<string> ProcessUrlAsync(string url) { using (var webClient = new WebClient()) { string data = await webClient.DownloadStringTaskAsync(new Uri(url)); // run checks here.. return data; } } // ... if (ListOfUrls.Count > 0) { var tasks = new List<Task>(); foreach (var url in ListOfUrls) { tasks.Add(ProcessUrlAsync(url)); } Task.WaitAll(tasks.ToArray()); // blocking wait // could use await here and make this method async: // await Task.WhenAll(tasks.ToArray()); }