Proceso paralelo una función IO intensiva
-
27-10-2019 - |
Pregunta
Tengo este código de muestra.
List<Dictionary<string,string>> objects = new List<Dictionary<string,string>>();
foreach (string url in urls)
{
objects.add(processUrl(url))
}
Necesito procesar la URL, processUrl
Abra la página y ejecute muchos regex para extraer algunas información y devolver un objeto "C# json", por lo que quiero ejecutar esto en paralelos y al final necesito una lista de objetos, por lo que necesito esperar todas las tareas para continuar el proceso , ¿Cómo puedo lograr esto? Tengo muchos ejemplo, pero ninguno ahorra el regreso.
Saludos
Solución
¿Como esto?
var results = urls.AsParallel().Select(processUrl).ToList();
Con Parallel
:
Parallel.ForEach(
urls,
url =>
{
var result = processUrl(url);
lock (syncOjbect)
objects.Add(result);
};
o
var objects = new ConcurrentBag<Dictionary<string,string>>();
Parallel.ForEach(urls, url => objects.Add(processUrl(url)));
var result = objects.ToList();
o con tareas:
var tasks = urls
.Select(url => Task.Factory.StartNew(() => processUrl(url)))
.ToArray();
Task.WaitAll(tasks);
var restuls = tasks.Select(arg => arg.Result).ToList();
Otros consejos
Primero, refactor como
processUrl(url, objects);
y haga que la tarea sea responsable de agregar los resultados a la lista.
Luego agregue el bloqueo para que dos tareas paralelas no intenten usar la lista de resultados exactamente al mismo tiempo.
Nota: async
El soporte en la próxima versión de .NET lo hará trivialmente fácil.
Puede usar extensiones Plinq, esto requiere .NET 4.0
System.Threading.Tasks.Parallel
.ForEach(urls, url => {
var result = processUrl(url);
lock(objects)
{
objects.Add(result);
}
});