Grupo de subprocesos administrado

La clase System.Threading.ThreadPool proporciona a la aplicación un grupo de subprocesos de trabajo administrados por el sistema, que le permite concentrarse en las tareas de la aplicación en lugar de en la administración de los subprocesos. Si tiene tareas cortas que requieran procesamiento en segundo plano, el grupo de subprocesos administrados permite aprovechar fácilmente las ventajas de varios subprocesos. El uso del grupo de subprocesos es notablemente más sencilla en .NET Framework 4 y versiones posteriores, ya que puede crear objetos Task y Task<TResult> que realizan tareas asincrónicas en los subprocesos del grupo de subprocesos.

.NET usa los subprocesos del grupo de subprocesos para muchos fines, incluidas operaciones de biblioteca TPL, la finalización de E/S asincrónica, las devoluciones de llamada del temporizador, las operaciones de espera registradas, las llamadas de métodos asincrónicos mediante delegados y las conexiones de socket System.Net.

Características del grupo de subprocesos

Los subprocesos del grupo de subprocesos son subprocesos en segundo plano. Cada subproceso utiliza el tamaño de pila predeterminado, se ejecuta con la prioridad predeterminada y está en el contenedor multiproceso. Una vez que un subproceso del grupo de subprocesos finaliza su tarea, se devuelve a una cola de subprocesos en espera. Desde este momento se puede reutilizar. Esta reutilización permite que las aplicaciones eviten el costo que significa crear un nuevo subproceso para cada tarea.

Hay solo un grupo de subprocesos por cada proceso.

Excepciones en los subprocesos del grupo de subprocesos

Las excepciones no controladas en los subprocesos del grupo de subprocesos finalizan el proceso. Hay tres excepciones de esta regla:

Para más información, consulte Excepciones en subprocesos administrados.

Número máximo de subprocesos del grupo de subprocesos

El número de operaciones que se pueden poner en cola en el grupo de subprocesos está limitado únicamente por la memoria disponible. Sin embargo, el grupo de subprocesos limita el número de subprocesos que pueden estar activos en el proceso de forma simultánea. Si todos los subprocesos del grupo de subprocesos están ocupados, los elementos de trabajo adicionales se pondrán en cola hasta que estén disponibles subprocesos para ejecutarlos. El tamaño predeterminado del grupo de subprocesos de un proceso depende de varios factores, como el tamaño del espacio de direcciones virtuales. Un proceso puede llamar al método ThreadPool.GetMaxThreads para determinar el número de subprocesos.

El número máximo de subprocesos se puede controlar con los métodos ThreadPool.GetMaxThreads y ThreadPool.SetMaxThreads.

Nota

El código que hospeda Common Language Runtime puede establecer el tamaño con el método ICorThreadpool::CorSetMaxThreads.

Mínimos del grupo de subprocesos

El grupo de subprocesos ofrece nuevos subprocesos de trabajo o subprocesos de finalización de E/S a petición hasta que llega a un mínimo especificado para cada categoría. Puede utilizar el método ThreadPool.GetMinThreads para obtener estos valores mínimos.

Nota

Cuando la demanda es baja, el número real de subprocesos del grupo de subprocesos puede descender por debajo de los valores mínimos.

Cuando se alcanza el mínimo, el grupo de subprocesos puede crear subprocesos adicionales o esperar hasta que se completen algunas tareas. El grupo de subprocesos crea y destruye subprocesos de trabajo para optimizar el rendimiento, que se define como el número de tareas que se completan por unidad de tiempo. Si hay demasiados pocos subprocesos, puede que los recursos disponibles no se usen de manera óptima, mientras que si hay demasiados subprocesos, puede aumentar la contención de recursos.

Precaución

Puede utilizar el método ThreadPool.SetMinThreads para aumentar el número mínimo de subprocesos inactivos. Sin embargo, aumentar innecesariamente estos valores puede causar problemas de rendimiento. Si se inician demasiadas tareas al mismo tiempo, puede que todas ellas parezcan funcionar con lentitud. En la mayoría de los casos, el grupo de subprocesos funciona mejor con su propio algoritmo de asignación de subprocesos.

Uso del grupo de subprocesos

La manera más fácil de usar el grupo de subprocesos consiste en utilizar la biblioteca TPL. De forma predeterminada, los tipos de biblioteca TPL, como Task y Task<TResult>, usan subprocesos del grupo de subprocesos para ejecutar tareas.

También puede utilizar el grupo de subprocesos llamando a ThreadPool.QueueUserWorkItem desde código administrado (o ICorThreadpool::CorQueueUserWorkItem desde código no administrado) y pasando un delegado System.Threading.WaitCallback que represente al método que realiza la tarea.

Otra forma de usar el grupo de subprocesos es poner en cola los elementos de trabajo que están relacionados con una operación de espera mediante el método ThreadPool.RegisterWaitForSingleObject y pasar un System.Threading.WaitHandle que, cuando se señala o cuando se agota el tiempo de espera, llame al método representado por el delegado System.Threading.WaitOrTimerCallback. Los subprocesos del grupo de subprocesos se usan para invocar métodos de devolución de llamada.

Para ver los ejemplos, consulte las páginas de la API a la que se hace referencia.

Omisión de comprobaciones de seguridad

El grupo de subprocesos también proporciona los métodos ThreadPool.UnsafeQueueUserWorkItem y ThreadPool.UnsafeRegisterWaitForSingleObject. Utilice estos métodos solamente cuando tenga la seguridad de que la pila del llamador es irrelevante para las comprobaciones de seguridad que se realizan durante la ejecución de la tarea en cola. ThreadPool.QueueUserWorkItem y ThreadPool.RegisterWaitForSingleObject capturan la pila del llamador, que se combina en la pila del subproceso del grupo de subprocesos cuando el subproceso empieza a ejecutar una tarea. Si es necesaria una comprobación de seguridad, debe comprobarse toda la pila. La comprobación proporciona seguridad, pero también supone un coste para el rendimiento.

Cuándo no usar subprocesos del grupo de subprocesos

Hay varios escenarios en los que es adecuado crear y administrar sus propios subprocesos en lugar de utilizar subprocesos del grupo de subprocesos:

  • Necesita un subproceso en primer plano.
  • Necesita que un subproceso tenga una prioridad determinada.
  • Tiene tareas que hacen que el subproceso se bloquee durante largos períodos de tiempo. El grupo de subprocesos tiene un número máximo de subprocesos, por lo que si hay un gran número de subprocesos del grupo de subprocesos bloqueados, esto puede impedir que se inicien las tareas.
  • Debe colocar los subprocesos en un contenedor uniproceso. Todos los subprocesos ThreadPool están en el contenedor multiproceso.
  • Debe tener una identidad estable asociada al subproceso o dedicar un subproceso a una tarea.

Vea también