Si tiene muchas tareas lógicas que requieren un procesamiento constante y desea que se realice en paralelo, use el programador pool +.
Si necesita hacer sus tareas relacionadas con IO al mismo tiempo, como descargar cosas de servidores remotos o acceso a disco, pero necesita hacer esto una vez cada pocos minutos, luego cree sus propios hilos y elimínelos una vez que haya terminado.
Editar: sobre algunas consideraciones, utilizo grupos de subprocesos para el acceso a la base de datos, física / simulación, IA (juegos) y para tareas con script ejecutadas en máquinas virtuales que procesan muchas tareas definidas por el usuario.
Normalmente, un grupo consta de 2 subprocesos por procesador (probablemente 4 hoy en día), sin embargo, puede configurar la cantidad de subprocesos que desea, si sabe cuántos necesita.
Editar: La razón para hacer sus propios hilos es debido a los cambios de contexto (es decir, cuando los hilos necesitan intercambiarse dentro y fuera del proceso, junto con su memoria). Tener cambios de contexto inútiles, digamos que cuando no está usando sus hilos, simplemente dejarlos sentados como se podría decir, puede fácilmente reducir 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 solo están esperando, están consumiendo toneladas de CPU y enfriando el caché para su aplicación real
Te sugiero que uses un grupo de subprocesos en C # por los mismos motivos 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 pequeñas tareas, el libro que lee significa tareas con una vida corta. Si lleva diez segundos crear un hilo que solo se ejecuta durante un segundo, ese es un lugar donde debería usar grupos (ignore mis cifras reales, es la relación lo que cuenta).
De lo contrario, pasa la mayor parte de su tiempo creando y destruyendo hilos en lugar de simplemente hacer el trabajo que están destinados a hacer.
fuente
Aquí hay un buen resumen del grupo de hilos 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 hilos y comenzar su propio hilo.
fuente
Recomiendo leer este libro electrónico gratuito: Threading in C # por Joseph Albahari
Al menos lea la sección "Introducción". El libro electrónico ofrece una excelente introducción e incluye una gran cantidad de información avanzada sobre subprocesos.
Saber si usar o no el grupo de subprocesos es solo el comienzo. A continuación, deberá determinar qué método de ingresar al grupo de hilos se adapta mejor a sus necesidades:
Este libro electrónico explica todo esto y aconseja cuándo usarlos en lugar de crear su propio hilo.
fuente
El grupo de subprocesos está diseñado para reducir el cambio de contexto entre sus subprocesos. Considere un proceso que tiene varios componentes en ejecución. Cada uno de esos componentes podría estar creando hilos de trabajo. Cuantos más subprocesos haya en su proceso, más tiempo se perderá en el cambio de contexto.
Ahora, si cada uno de esos componentes fueran elementos en cola para el grupo de subprocesos, tendría mucho menos gastos generales de cambio de contexto.
El grupo de subprocesos está diseñado para maximizar el trabajo que se realiza en sus CPU (o núcleos de CPU). Es por eso que, de manera predeterminada, el grupo de subprocesos gira varios subprocesos por procesador.
Hay algunas situaciones en las que no desea utilizar el grupo de subprocesos. Si está esperando E / S, o esperando un evento, etc., entonces ata ese hilo del grupo de subprocesos y nadie más puede usarlo. La misma idea se aplica a las tareas de larga duración, aunque lo que constituye una tarea de larga duración es subjetiva.
Pax Diablo también hace un buen punto. Girar hilos no es gratis. 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 asíncrona (también conocido como los métodos BeginXX y EndXX). Por un
FileStream
que seríaBeginRead
yEndRead
. Por unHttpWebRequest
que seríaBeginGetResponse
yEndGetResponse
. Son más complicados de usar, pero son la forma correcta de realizar E / S multiproceso.fuente
Tenga cuidado con el grupo de subprocesos de .NET para las operaciones que pueden bloquear cualquier parte significativa, variable o desconocida de su procesamiento, ya que es propenso a la inanición de subprocesos. Considere usar las extensiones paralelas de .NET, que proporcionan una buena cantidad de abstracciones lógicas sobre las operaciones de subprocesos. También incluyen un nuevo programador, que debería ser una mejora en ThreadPool. Ver aquí
fuente
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 se usa uno 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.
fuente
Si tiene una tarea en segundo plano que durará mucho tiempo, como toda la vida útil de su aplicación, crear su propio hilo es algo razonable. Si tiene trabajos cortos que deben realizarse en un subproceso, utilice la agrupación de subprocesos.
En una aplicación donde está creando muchos subprocesos, la sobrecarga de crear los subprocesos se vuelve sustancial. El uso del grupo de subprocesos crea los subprocesos una vez y los reutiliza, evitando así la sobrecarga de creación de subprocesos.
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 superar la aplicación.
fuente
Para obtener el máximo rendimiento con unidades que se ejecutan simultáneamente, escriba su propio grupo de subprocesos, donde se crea un grupo de objetos de subprocesos al inicio y se pasa al bloqueo (anteriormente suspendido), esperando que se ejecute un contexto (un objeto con una interfaz estándar implementada por tu codigo).
Muchos artículos sobre Tareas frente a subprocesos frente a .NET ThreadPool no le ofrecen realmente lo que necesita para tomar una decisión de rendimiento. Pero cuando los comparas, los hilos ganan y especialmente un grupo de hilos. Se distribuyen mejor entre las CPU y se inician más rápido.
Lo que debe discutirse es el hecho de que la unidad de ejecución principal de Windows (incluido Windows 10) es un subproceso, y la sobrecarga de cambio 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 afirme un mayor rendimiento al guardar el cambio de contexto o un mejor uso de la CPU.
Ahora por un poco de realismo:
La mayoría de nosotros no necesitará 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.
Entonces, lo que puede ser más importante es discutir qué es fácil de programar.
Si crea su propio grupo de subprocesos, tendrá que escribir un poco, ya que deberá preocuparse por el seguimiento del estado de ejecución, cómo simular la suspensión y la reanudación, y cómo cancelar la ejecución, incluso en toda una aplicación apagar. Es posible que también deba preocuparse si desea hacer crecer dinámicamente su grupo y también qué limitación de capacidad tendrá su grupo. Puedo escribir ese 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 puede crear una y ponerla en línea en su código (aunque se debe tener precaución). Puede pasar un token de cancelación para controlar cuándo desea cancelar la Tarea. Además, utiliza el enfoque de promesa para encadenar eventos, y puede hacer que devuelva un tipo específico de valor. Además, con async y wait, existen más opciones y su código será más portátil.
En esencia, es importante comprender los pros y los contras con Tareas vs. Threads vs. .NET ThreadPool. Si necesito un alto rendimiento, voy a usar hilos, y prefiero usar mi propio grupo.
Una manera fácil de comparar es iniciar 512 hilos, 512 tareas y 512 hilos de ThreadPool. Al principio encontrará un retraso con los subprocesos (por lo tanto, por qué escribir un grupo de subprocesos), pero los 512 subprocesos 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), que se ejecutan cada 30 segundos. El código ejecutado realiza E / S de archivo simple en una unidad SSD.
Resultados de la prueba
fuente
Los grupos de subprocesos son excelentes cuando tiene que procesar más tareas 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.
Consulte esta página en MSDN: http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80).aspx
fuente
Utilice siempre un grupo de subprocesos si puede, trabaje al más alto nivel de abstracción posible. Los grupos de subprocesos ocultan crear y destruir subprocesos para usted, ¡esto generalmente es algo bueno!
fuente
La mayoría de las veces puede usar el grupo ya que evita el costoso proceso de crear el hilo.
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, por ejemplo, si desea controlar el tamaño de pila del subproceso.
fuente
No olvides investigar al trabajador de fondo.
Encuentro muchas situaciones, me da justo lo que quiero sin el trabajo pesado.
Salud.
fuente
Usualmente uso el Threadpool cuando necesito hacer algo en otro hilo y realmente no me importa cuándo se ejecuta o termina. Algo como el registro o tal vez incluso la descarga en segundo plano de un archivo (aunque hay mejores formas de hacerlo al estilo asíncrono). Uso mi propio hilo cuando necesito más control. También lo que he encontrado es que usar una cola Threadsafe (hackear la tuya propia) para almacenar "objetos de comando" es bueno cuando tengo varios comandos en los que necesito trabajar en> 1 hilo. Por lo tanto, puede dividir un archivo Xml y poner cada elemento en una cola y luego tener varios subprocesos trabajando en hacer un procesamiento en estos elementos. Escribí tal cola en uni (¡VB.net!) Que he convertido a C #. Lo he incluido a continuación sin ningún motivo en particular (este código puede contener algunos errores).
fuente
Quería un grupo de subprocesos para distribuir el trabajo entre los 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 substituto de 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 dividir los cálculos repetitivos en partes que se pueden ejecutar en paralelo (suponiendo que se puedan ejecutar en paralelo sin cambiar el resultado). La gestión manual de subprocesos es útil para tareas como IU e IO.
fuente