44 votos

Generar Varios Subprocesos para el trabajo, a continuación, espere hasta que todo terminó

solo quiero algunos consejos sobre "mejores prácticas" en relación multi-threading tareas.

como ejemplo, tenemos una aplicación en C# que en el inicio lee los datos de varios "tipo" de la tabla en nuestra base de datos y almacena la información en una colección en la que pasamos alrededor de la aplicación. esto nos impide golpear la base de datos cada vez que esta información es necesaria.

en el momento en que la solicitud es la lectura de datos de 10 tablas de forma sincrónica. realmente me gustaría tener la aplicación de lectura de cada tabla en un subproceso diferente a todos los que se ejecutan en paralelo. la aplicación sería esperar a que todos los hilos se complete antes de continuar con el arranque de la aplicación.

he mirado en BackGroundWorker, pero sólo quiero un consejo sobre el cumplimiento de las anteriores.

  1. ¿El método de la sana lógica con el fin de acelerar el tiempo de inicio de nuestra aplicación
  2. ¿Cómo podemos manejar todos los hilos teniendo en cuenta que cada hilo de la obra es independiente el uno del otro, solo tenemos que esperar a que todos los hilos se complete antes de continuar.

espero algunas respuestas

79voto

Reed Copsey Puntos 315315

Mi preferencia por esto es controlar a través de una sola WaitHandle, y el uso de Enclavamiento para evitar el bloqueo en un contador:

class Program
{
    static void Main(string[] args)
    {
        int numThreads = 10;
        ManualResetEvent resetEvent = new ManualResetEvent(false);
        int toProcess = numThreads;

        // Start workers.
        for (int i = 0; i < numThreads; i++)
        {
            new Thread(delegate()
            {
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                // If we're the last thread, signal
                if (Interlocked.Decrement(ref toProcess) == 0)
                    resetEvent.Set();
            }).Start();
        }

        // Wait for workers.
        resetEvent.WaitOne();
        Console.WriteLine("Finished.");
    }
}

Esto funciona bien, y se adapta a cualquier número de hilos de procesamiento, sin la introducción de bloqueo.

20voto

Jack Leitch Puntos 464

Me gusta @Reed solución. Otra forma de lograr el mismo .NET 4.0 sería el uso de un CountdownEvent.

class Program
{
    static void Main(string[] args)
    {
        var numThreads = 10;
        var countdownEvent = new CountdownEvent(numThreads);

        // Start workers.
        for (var i = 0; i < numThreads; i++)
        {
            new Thread(delegate()
            {
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                // Signal the CountdownEvent.
                countdownEvent.Signal();
            }).Start();
        }

        // Wait for workers.
        countdownEvent.Wait();
        Console.WriteLine("Finished.");
    }
}

8voto

Karol Puntos 183

Si usted tiene más de 64 esperar asas para un Subproceso STA como dice Marcos. puede crear una lista con tus hilos y esperar a que todo terminar en un segundo bucle.

//check that all threads have completed.
foreach (Thread thread in threadList)
{
     thread.Join();

}  

7voto

Mark Byers Puntos 318575

Si no estás en .NET 4.0, a continuación, puede utilizar una Lista de<ManualResetEvent>, uno para cada subproceso y Esperar para que ellos se Establezca. A esperar en varios subprocesos usted podría considerar el uso de WaitAll pero ten cuidado con el límite de 64 esperar asas. Si usted necesita más que esto, sólo puede bucle sobre ellos y esperar a que cada uno de ellos individualmente.

Si desea un inicio más rápido exprience, probablemente usted no necesita esperar a que la lectura de los datos durante el inicio. Solo mostrar la interfaz gráfica de usuario y cualquier otra información que falta puede ser mostrado en gris con algún tipo de "Actualizando..." icono o similar. Cuando la información llega, acaba de despedir a un evento para actualizar la interfaz gráfica de usuario. Podría haber muchas de las operaciones que el usuario puede comenzar a realizar incluso antes de que todos los datos de todas las tablas se lee en.

5voto

Karol Puntos 183

Si te sientes aventurero se puede utilizar C# 4.0 y la Task Parallel Library:

Parallel.ForEach(jobList, curJob => {
  curJob.Process()
});

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X