Grupos de subprocesos

Un grupo de subprocesos es una colección de subprocesos de trabajo que ejecutan de forma eficiente devoluciones de llamada asincrónicas en nombre de la aplicación. El grupo de subprocesos se usa principalmente para reducir el número de subprocesos de la aplicación y administrar los subprocesos de trabajo. Las aplicaciones pueden poner en cola elementos de trabajo, asociar el trabajo con identificadores de espera, poner automáticamente en cola en función de un temporizador y enlazar con E/S.

Arquitectura del grupo de subprocesos

Las siguientes aplicaciones pueden beneficiarse del uso de un grupo de subprocesos:

  • Una aplicación muy paralela que puede enviar un gran número de elementos de trabajo pequeños de forma asincrónica (como la búsqueda de índices distribuidos o la E/S de red).
  • Una aplicación que crea y destruye un gran número de subprocesos que se ejecutan durante un tiempo corto. El uso del grupo de subprocesos puede reducir la complejidad de la administración de subprocesos y la sobrecarga implicada en la creación y destrucción de subprocesos.
  • Una aplicación que procesa elementos de trabajo independientes en segundo plano y en paralelo (como cargar varias pestañas).
  • Una aplicación que debe realizar una espera exclusiva en objetos kernel o bloquear eventos entrantes en un objeto. El uso del grupo de subprocesos puede reducir la complejidad de la administración de subprocesos y aumentar el rendimiento al disminuir el número de modificadores de contexto.
  • Una aplicación que crea subprocesos de espera personalizados para esperar eventos.

El grupo de subprocesos original se ha rediseñado completamente en Windows Vista. El nuevo grupo de subprocesos se ha mejorado porque proporciona un único tipo de subproceso de trabajo (admite E/S y no E/S), no usa un subproceso de temporizador, proporciona una sola cola de temporizador y proporciona un subproceso persistente dedicado. También proporciona grupos de limpieza, un mayor rendimiento, varios grupos por proceso programados de forma independiente y una nueva API de grupo de subprocesos.

La arquitectura de grupo de subprocesos consta de los siguientes componentes:

  • Subprocesos de trabajo que ejecutan las funciones de devolución de llamada
  • Subprocesos de espera que esperan varios identificadores de espera
  • Una cola de trabajo
  • Un grupo de subprocesos predeterminado para cada proceso
  • Una fábrica de trabajo que administra los subprocesos de trabajo

Procedimientos recomendados

La nueva API de grupo de subprocesos proporciona más flexibilidad y control que la API del grupo de subprocesos original. Aun así, hay algunas diferencias sutiles pero importantes. En la API original, el restablecimiento de espera era automático; en la nueva API, la espera se debe restablecer explícitamente cada vez. La API original controlaba la suplantación automáticamente y transfería el contexto de seguridad del proceso de llamada al subproceso. Con la nueva API, la aplicación debe establecer explícitamente el contexto de seguridad.

Estos son los procedimientos recomendados al usar un grupo de subprocesos:

  • Los subprocesos de un proceso comparten el grupo de subprocesos. Un único subproceso de trabajo puede ejecutar varias funciones de devolución de llamada de una en una. El grupo de subprocesos administra estos subprocesos de trabajo. Por lo tanto, no finalice un subproceso del grupo de subprocesos llamando a TerminateThread en el subproceso o llamando a ExitThread desde una función de devolución de llamada.

  • Una solicitud de E/S se puede ejecutar en cualquier subproceso del grupo de subprocesos. La cancelación de E/S en un subproceso de grupo de subprocesos requiere sincronización, ya que la función cancel se puede ejecutar en un subproceso diferente al que controla la solicitud de E/S, lo que puede dar lugar a la cancelación de una operación desconocida. Para evitar esto, proporcione siempre la estructura OVERLAPPED con la que se inició una solicitud de E/S al llamar a CancelIoEx para E/S asincrónica o use su propia sincronización para asegurarse de que no se pueda iniciar ninguna otra E/S en el subproceso de destino antes de llamar a la función CancelSynchronousIo o CancelIoEx.

  • Limpie todos los recursos creados en la función de devolución de llamada antes de volver de la función. Entre ellos se incluyen TLS, los contextos de seguridad, la prioridad del subproceso y el registro COM. Las funciones de devolución de llamada también deben restaurar el estado del subproceso antes de volver.

  • Mantenga activos los identificadores de espera y sus objetos asociados hasta que el grupo de subprocesos haya indicado que ha terminado con el identificador.

  • Marque todos los subprocesos que esperan operaciones largas (como vaciados de E/S o limpieza de recursos) para que el grupo de subprocesos pueda asignar nuevos subprocesos en lugar de esperar a que se complete este.

  • Antes de descargar un archivo DLL que use el grupo de subprocesos, cancele todos los elementos de trabajo, E/S, las operaciones de espera y los temporizadores, y espere a que se complete la ejecución de las devoluciones de llamada.

  • Evite interbloqueos eliminando las dependencias entre elementos de trabajo y entre devoluciones de llamada. Para ello, asegúrese de que una devolución de llamada no está esperando a completarse y conserve la prioridad del subproceso.

  • No ponga en cola demasiados elementos demasiado deprisa en un proceso con otros componentes que usen el grupo de subprocesos predeterminado. Hay un grupo de subprocesos predeterminado por proceso, incluido Svchost.exe. De forma predeterminada, cada grupo de subprocesos tiene un máximo de 500 subprocesos de trabajo. El grupo de subprocesos intenta crear más subprocesos de trabajo cuando el número de subprocesos de trabajo en estado listo o en ejecución debe ser menor que el número de procesadores.

  • Evite el modelo de contenedor de un solo subproceso COM, ya que no es compatible con el grupo de subprocesos. STA crea el estado del subproceso que puede afectar al siguiente elemento de trabajo del subproceso. STA suele ser de larga duración y tiene afinidad de subproceso, que es lo contrario al grupo de subprocesos.

  • Cree un nuevo grupo de subprocesos para controlar la prioridad y el aislamiento de los subprocesos, crear características personalizadas y, posiblemente, mejorar la capacidad de respuesta. Sin embargo, los grupos de subprocesos adicionales requieren más recursos del sistema (subprocesos, memoria del kernel). Un número demasiado alto de grupos aumenta la posibilidad de contención de CPU.

  • Si es posible, use un objeto de espera en lugar de un mecanismo basado en APC para indicar un subproceso de grupo de subprocesos. Las API no funcionan tan bien con los subprocesos del grupo de subprocesos como otros mecanismos de señalización porque el sistema controla la duración de los subprocesos del grupo de subprocesos, de modo que es posible que un subproceso finalice antes de que se entregue la notificación.

  • Use la extensión del depurador del grupo de subprocesos, !tp. Este comando tiene el siguiente uso:

    • pool dirección marcas
    • obj dirección marcas
    • tqueue dirección marcas
    • waiter dirección
    • worker dirección

    Para pool, waiter y worker, si la dirección es cero, el comando vuelca todos los objetos. Para waiter y worker, cuando se omiten las direcciones se vuelca el subproceso actual. Se definen las marcas siguientes: 0x1 (salida de una sola línea), 0x2 (miembros de volcado) y 0x4 (cola de trabajo del grupo de volcados).

API de grupo de subprocesos

Uso de las funciones del grupo de subprocesos