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

¿Fue útil?

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);
             }
           });
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top