[c#] ¿Cómo puedo recopilar los valores devueltos de Parallel.ForEach?



1 Answers

Puede considerar utilizar el método de extensión AsParallel de IEnumerable , se ocupará de la concurrencia y recopilará los resultados.

words.AsParallel().Select(AddB).ToArray()

La sincronización (por ejemplo, bloqueos o colecciones concurrentes que utilizan bloqueos) suele ser un cuello de botella de algoritmos concurrentes. Lo mejor es evitar la sincronización tanto como sea posible. Supongo que AsParallel utiliza algo más inteligente como colocar todos los elementos producidos en un solo hilo en una colección local no concurrente y luego combinarlos al final.

Question

Estoy llamando a un servicio web lento en paralelo. Las cosas fueron geniales hasta que me di cuenta de que necesitaba obtener algo de información del servicio. Pero no veo dónde recuperar los valores. No puedo escribir en la base de datos, HttpContext.Current parece ser nulo dentro de un método llamado usando Parallel.ForEach

A continuación se muestra un programa de ejemplo (en su mente, imagine un servicio web lento en lugar de una concatenación de cadenas)

using System;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        WordMaker m = new WordMaker();
        m.MakeIt();
    }
    public class WordMaker
    {
        public void MakeIt()
        {
            string[] words = { "ack", "ook" };
            ParallelLoopResult result = Parallel.ForEach(words, word => AddB(word));
            Console.WriteLine("Where did my results go?");
            Console.ReadKey();
        }
        public string AddB(string word)
        {
            return "b" + word;
        }
    }

}



Qué tal algo como esto:

public class WordContainer
{
    public WordContainer(string word)
    {
        Word = word;
    }

    public string Word { get; private set; }
    public string Result { get; set; }
}

public class WordMaker
{
    public void MakeIt()
    {
        string[] words = { "ack", "ook" };
        List<WordContainer> containers = words.Select(w => new WordContainer(w)).ToList();

        Parallel.ForEach(containers, AddB);

        //containers.ForEach(c => Console.WriteLine(c.Result));
        foreach (var container in containers)
        {
            Console.WriteLine(container.Result);
        }

        Console.ReadKey();
    }

    public void AddB(WordContainer container)
    {
        container.Result = "b" + container.Word;
    }
}

Creo que el bloqueo o los objetos concurrentes no son necesarios a menos que necesite los resultados para interactuar entre sí (como si estuviera calculando una suma o combinando todas las palabras). En este caso, ForEach divide cuidadosamente su lista original y le entrega a cada hilo su propio objeto para que pueda manipular todo lo que quiera sin preocuparse de interferir con los otros hilos.




Related