¿Cuándo usar thread pool en C#?


He estado tratando de aprender programación multihilo en C# y estoy confundido acerca de cuándo es mejor usar un grupo de subprocesos frente a crear mis propios subprocesos. Un libro recomienda usar un grupo de subprocesos solo para tareas pequeñas (lo que sea que eso signifique), pero parece que no puedo encontrar ninguna guía real. ¿Cuáles son algunas consideraciones que utiliza al tomar esta decisión de programación?

Author: participant, 2008-09-28

15 answers

Si tiene muchas tareas lógicas que requieren un procesamiento constante y desea que se realicen en paralelo, use el pool+scheduler.

Si necesita hacer sus tareas relacionadas con IO simultáneamente, como descargar cosas de servidores remotos o acceso a disco, pero necesita hacer esto, digamos, una vez cada pocos minutos, luego haga sus propios hilos y mátelos una vez que haya terminado.

Editar: Sobre algunas consideraciones, uso grupos de subprocesos para el acceso a la base de datos, física / simulación, IA (juegos) y para tareas con scripts ejecutadas en máquinas virtuales que procesan muchas tareas definidas por el usuario.

Normalmente un grupo consta de 2 subprocesos por procesador (tan probablemente 4 hoy en día), sin embargo, puede configurar la cantidad de subprocesos que desee, si sabe cuántos necesita.

Editar: La razón para hacer tus propios hilos es debido a los cambios de contexto, (es cuando los hilos necesitan intercambiar dentro y fuera del proceso, junto con su memoria). Tener cambios de contexto inútiles, digamos cuando no estás usando tu los hilos, simplemente dejándolos sentados como se podría decir, pueden fácilmente la mitad del rendimiento de su programa (digamos que tiene 3 hilos dormidos y 2 hilos activos). Por lo tanto, si los hilos de descarga están esperando están comiendo toneladas de CPU y enfriando la caché para su aplicación real

 44
Author: Robert Gould,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-13 14:26:45

Le sugeriría que use un grupo de subprocesos en C# por las mismas razones que cualquier otro lenguaje.

Cuando desee limitar el número de subprocesos en ejecución o no desee la sobrecarga de crearlos y destruirlos, use un grupo de subprocesos.

Por tareas pequeñas, el libro que lees significa tareas con una vida útil corta. Si se tarda diez segundos en crear un hilo que solo se ejecuta durante un segundo, ese es un lugar donde debería estar utilizando grupos (ignore mis cifras reales, es la proporción que contar).

De lo contrario, pasas la mayor parte de tu tiempo creando y destruyendo hilos en lugar de simplemente hacer el trabajo que están destinados a hacer.

 47
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-26 08:35:49

Aquí hay un buen resumen del grupo de subprocesos en. Net: http://blogs.msdn.com/pedram/archive/2007/08/05/dedicated-thread-or-a-threadpool-thread.aspx

La publicación también tiene algunos puntos sobre cuándo no debe usar el grupo de subprocesos e iniciar su propio subproceso en su lugar.

 28
Author: Franci Penov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-28 06:13:51

Recomiendo encarecidamente leer este libro electrónico gratuito: Enhebrado en C # por Joseph Albahari

Al menos lee la sección "Primeros pasos". El libro electrónico proporciona una gran introducción e incluye una gran cantidad de información avanzada de enhebrado también.

Saber si usar o no el grupo de subprocesos es solo el principio. A continuación, deberá determinar qué método de ingresar al grupo de subprocesos se adapta mejor a sus necesidades:

  • Biblioteca paralela de tareas (. NET Marco 4.0)
  • ThreadPool.QueueUserWorkItem
  • Delegados asíncronos
  • BackgroundWorker

Este libro electrónico explica todo esto y aconseja cuándo usarlos o crear tu propio hilo.

 14
Author: jrupe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-29 14:09:37

El grupo de subprocesos está diseñado para reducir el cambio de contexto entre los subprocesos. Considere un proceso que tiene varios componentes en ejecución. Cada uno de esos componentes podría estar creando subprocesos de trabajo. Cuantos más hilos haya en el proceso, más tiempo se perderá en el cambio de contexto.

Ahora, si cada uno de esos componentes estuviera haciendo cola en el grupo de subprocesos, tendría mucha menos sobrecarga de cambio de contexto.

El grupo de subprocesos está diseñado para maximizar el trabajo que se sus CPU (o núcleos de CPU). Es por eso que, de forma predeterminada, el grupo de subprocesos gira varios subprocesos por procesador.

Hay algunas situaciones en las que no querrás usar el grupo de subprocesos. Si está esperando en E / S, o esperando en un evento, etc., entonces ata ese hilo del grupo de hilos y no puede ser utilizado por nadie más. La misma idea se aplica a las tareas de larga duración, aunque lo que constituye una tarea de larga duración es subjetivo.

Pax Diablo también hace un buen punto. Girando hilos no es libre. Lleva tiempo y consumen memoria adicional para su espacio de pila. El grupo de subprocesos reutilizará los subprocesos para amortizar este costo.

Nota: preguntó sobre el uso de un subproceso de grupo de subprocesos para descargar datos o realizar E/S de disco.No debe usar un subproceso de grupo de subprocesos para esto (por las razones que describí anteriormente). En su lugar, use E/S asincrónicas (también conocidos como los métodos BeginXX y EndXX). Para un FileStream que sería BeginRead y EndRead. Para un HttpWebRequest que sería BeginGetResponse y EndGetResponse. Son más complicados de usar, pero son la forma adecuada de realizar E/S multi-threaded

 8
Author: Brannon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-28 08:01:30

Tenga cuidado con el grupo de subprocesos.NET para operaciones que pueden bloquearse para cualquier parte significativa, variable o desconocida de su procesamiento, ya que es propenso a la inanición de subprocesos. Considere el uso de las extensiones paralelas.NET, que proporcionan un buen número de abstracciones lógicas sobre operaciones enhebradas. También incluyen un nuevo programador, que debería ser una mejora en ThreadPool. Ver aquí

 6
Author: mancaus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-30 10:59:15

Una razón para usar el grupo de subprocesos solo para tareas pequeñas es que hay un número limitado de subprocesos de grupo de subprocesos. Si uno se utiliza durante mucho tiempo, entonces detiene ese hilo de ser utilizado por otro código. Si esto sucede muchas veces, el grupo de subprocesos puede agotarse.

Usar el grupo de subprocesos puede tener efectos sutiles - algunos temporizadores.NET usan subprocesos de grupo de subprocesos y no se activarán, por ejemplo.

 3
Author: Thomas Bratt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-28 13:38:32

Para obtener el máximo rendimiento con unidades de ejecución simultáneas, escriba su propio grupo de subprocesos, donde se crea un grupo de objetos de subprocesos al iniciar y vaya a bloqueo (anteriormente suspendido), esperando que se ejecute un contexto (un objeto con una interfaz estándar implementada por su código).

Tantos artículos sobre Tareas vs.Hilos vs. el. NET ThreadPool no le dan realmente lo que necesita para tomar una decisión para el rendimiento. Pero cuando los comparas, los hilos ganan y especialmente un piscina de Hilos. Se distribuyen mejor entre las CPU y se inician más rápido.

Lo que se debe discutir es el hecho de que la unidad de ejecución principal de Windows (incluido Windows 10) es un subproceso, y la sobrecarga de conmutación de contexto del sistema operativo suele ser insignificante. En pocas palabras, no he podido encontrar evidencia convincente de muchos de estos artículos, ya sea que el artículo reclame un mayor rendimiento al guardar el cambio de contexto o un mejor uso de la CPU.

Ahora para un poco de realismo:

La mayoría de nosotros no necesitamos que nuestra aplicación sea determinista, y la mayoría de nosotros no tenemos un fondo duro con hilos, que por ejemplo a menudo viene con el desarrollo de un sistema operativo. Lo que escribí arriba no es para un principiante.

Así que lo que puede ser más importante es discutir es lo que es fácil de programar.

Si creas tu propio grupo de subprocesos, tendrás un poco de escritura que hacer, ya que tendrás que preocuparte por el seguimiento del estado de ejecución, cómo simule suspender y reanudar, y cómo cancelar la ejecución, incluso en un apagado de toda la aplicación. Es posible que también tenga que preocuparse por si desea hacer crecer dinámicamente su piscina y también qué limitación de capacidad tendrá su piscina. Puedo escribir tal marco en una hora, pero eso es porque lo he hecho muchas veces.

Quizás la forma más fácil de escribir una unidad de ejecución es usar una Tarea. La belleza de una tarea es que usted puede crear uno y ponerlo en marcha en línea en su código (aunque la precaución puede ser justificada). Puede pasar un token de cancelación para manejar cuando desee cancelar la tarea. Además, utiliza el enfoque promise para encadenar eventos, y puede hacer que devuelva un tipo específico de valor. Además, con async y await, existen más opciones y su código será más portátil.

En esencia, es importante entender los pros y los contras de las tareas frente a los hilos frente al.NET ThreadPool. Si necesito alto rendimiento, voy a usar hilos, y prefiero usar mi propia piscina.

Una manera fácil de comparar es iniciar 512 Hilos, 512 Tareas y 512 hilos ThreadPool. Encontrarás un retraso al principio con los subprocesos (por lo tanto, por qué escribir un grupo de subprocesos), pero todos los subprocesos 512 se ejecutarán en unos segundos, mientras que los subprocesos de Tareas y.NET ThreadPool tardan unos minutos en comenzar.

A continuación se muestran los resultados de dicha prueba (i5 quad core con 16 GB de RAM), dando cada 30 segundos para ejecutarse. El código ejecutado realiza E / S de archivo simples en una unidad SSD.

Resultados de las pruebas

 2
Author: Grabe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-27 15:42:54

Los grupos de subprocesos son excelentes cuando tiene más tareas que procesar que los subprocesos disponibles.

Puede agregar todas las tareas a un grupo de subprocesos y especificar el número máximo de subprocesos que se pueden ejecutar en un momento determinado.

Echa un vistazo a esta página en MSDN: http://msdn.microsoft.com/en-us/library/3dasc8as (VS.80).aspx

 1
Author: lajos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-28 06:07:46

Siempre use un grupo de subprocesos si puede, trabaje en el nivel más alto de abstracción posible. Grupos de hilos ocultar crear y destruir hilos para usted, esto suele ser una buena cosa!

 1
Author: JeffFoster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-28 06:08:25

La mayoría de las veces puedes usar el pool para evitar el costoso proceso de crear el subproceso.

Sin embargo, en algunos escenarios es posible que desee crear un hilo. Por ejemplo, si no es el único que usa el grupo de subprocesos y el subproceso que crea es de larga duración (para evitar consumir recursos compartidos) o si desea controlar el tamaño de pila del subproceso.

 1
Author: antonio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-28 08:01:06

Si tienes una tarea en segundo plano que durará mucho tiempo, como toda la vida útil de tu aplicación, entonces crear tu propio hilo es algo razonable. Si tiene trabajos cortos que deben realizarse en un subproceso, use agrupación de subprocesos.

En una aplicación en la que está creando muchos subprocesos, la sobrecarga de la creación de los subprocesos se vuelve sustancial. El uso del grupo de subprocesos crea los subprocesos una vez y los reutiliza, evitando así la creación de subprocesos sobrecarga.

En una aplicación en la que trabajé, cambiar de crear subprocesos a usar el grupo de subprocesos para los subprocesos de corta duración realmente ayudó a la aplicación.

 1
Author: Bill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-13 14:21:02

No olvide investigar al trabajador en segundo plano.

Me parece que para un montón de situaciones, me da justo lo que quiero sin el trabajo pesado.

Salud.
 1
Author: SetiSeeker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-26 05:48:24

Normalmente uso el Threadpool cada vez que necesito hacer algo en otro hilo y realmente no me importa cuando se ejecuta o termina. Algo como registrar o tal vez incluso descargar un archivo en segundo plano (aunque hay mejores maneras de hacer ese estilo asíncrono). Uso mi propio hilo cuando necesito más control. También lo que he encontrado es usar una cola Threadsafe (hackear su propio) para almacenar "objetos de comando" es bueno cuando tengo varios comandos que necesito trabajar en >1 hilo. Así que podrías dividir un Xml archivar y poner cada elemento en una cola y luego tener varios subprocesos trabajando en hacer algún procesamiento en estos elementos. Escribí una cola así en la uni (VB.net!) que he convertido a C#. Lo he incluido a continuación sin ninguna razón en particular (este código podría contener algunos errores).

using System.Collections.Generic;
using System.Threading;

namespace ThreadSafeQueue {
    public class ThreadSafeQueue<T> {
        private Queue<T> _queue;

        public ThreadSafeQueue() {
            _queue = new Queue<T>();
        }

        public void EnqueueSafe(T item) {
            lock ( this ) {
                _queue.Enqueue(item);
                if ( _queue.Count >= 1 )
                    Monitor.Pulse(this);
            }
        }

        public T DequeueSafe() {
            lock ( this ) {
                while ( _queue.Count <= 0 )
                    Monitor.Wait(this);

                return this.DeEnqueueUnblock();

            }
        }

        private T DeEnqueueUnblock() {
            return _queue.Dequeue();
        }
    }
}
 0
Author: noocyte,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-16 13:42:47

Quería un grupo de subprocesos para distribuir el trabajo entre núcleos con la menor latencia posible, y eso no tenía que funcionar bien con otras aplicaciones. Descubrí que el rendimiento del grupo de subprocesos.NET no era tan bueno como podría ser. Sabía que quería un hilo por núcleo, así que escribí mi propia clase de sustituto del grupo de hilos. El código se proporciona como respuesta a otra pregunta de StackOverflow aquí.

En cuanto a la pregunta original, el grupo de subprocesos es útil para romper repetitivo cálculos en partes que se pueden ejecutar en paralelo (suponiendo que se pueden ejecutar en paralelo sin cambiar el resultado). La administración manual de subprocesos es útil para tareas como UI y IO.

 0
Author: cdiggins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:19