Opciones de configuración de ejecución para subprocesos

En este artículo se detallan los valores que puede usar para configurar el subproceso en .NET.

Nota:

.NET 6 estandariza en el prefijo DOTNET_ en lugar de en COMPlus_ para las variables de entorno que configuran el comportamiento en tiempo de ejecución de .NET. Sin embargo, el prefijo COMPlus_ seguirá funcionando. Si usa una versión anterior del runtime de .NET, debe seguir usando el prefijo COMPlus_ para las variables de entorno.

Uso de todos los grupos de CPU en Windows

  • En las máquinas que tienen varios grupos de CPU, esta opción configura si los componentes, como el grupo de subprocesos, usan todos los grupos de CPU o solo el grupo de CPU principal del proceso. Esta opción también afecta a lo que Environment.ProcessorCount devuelve.
  • Cuando esta opción está habilitada, todos los grupos de CPU se usan y los subprocesos también se distribuyen automáticamente entre los grupos de CPU de forma predeterminada.
  • Esta opción está habilitada de forma predeterminada en Windows 11 y versiones posteriores, y deshabilitada de forma predeterminada en Windows 10 y versiones anteriores. Para que esta opción surta efecto cuando está habilitada, el GC también debe configurarse para usar todos los grupos de CPU; para más información, consulte Grupos de CPU del GC.
Nombre de valor Valores
runtimeconfig.json N/D N/D
Variable del entorno COMPlus_Thread_UseAllCpuGroups o DOTNET_Thread_UseAllCpuGroups 0: deshabilitado.
1: habilitado.

Asignación de subprocesos a grupos de CPU en Windows

  • En las máquinas que tienen varios grupos de CPU y en las que todos ellos están en uso, esta opción configura si los subprocesos se distribuyen automáticamente entre los grupos de CPU.
  • Cuando esta opción está habilitada, los nuevos subprocesos se asignan a un grupo de CPU de forma que intenta rellenar completamente un grupo de CPU que ya está en uso antes de usar un nuevo grupo de CPU.
  • Esta opción está habilitada de forma predeterminada.
Nombre de valor Valores
runtimeconfig.json N/D N/D
Variable del entorno COMPlus_Thread_AssignCpuGroups o DOTNET_Thread_AssignCpuGroups 0: deshabilitado.
1: habilitado.

Mínimo de subprocesos

  • Especifica el número mínimo de subprocesos para el grupo de subprocesos de trabajo.
  • Corresponde al método ThreadPool.SetMinThreads.
Nombre de valor Valores
runtimeconfig.json System.Threading.ThreadPool.MinThreads Entero que representa el número mínimo de subprocesos.
Propiedad de MSBuild ThreadPoolMinThreads Entero que representa el número mínimo de subprocesos.
Variable del entorno N/D N/D

Ejemplos

Archivo runtimeconfig.json:

{
   "runtimeOptions": {
      "configProperties": {
         "System.Threading.ThreadPool.MinThreads": 4
      }
   }
}

archivo runtimeconfig.template.json:

{
   "configProperties": {
      "System.Threading.ThreadPool.MinThreads": 4
   }
}

Archivo del proyecto:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <ThreadPoolMinThreads>4</ThreadPoolMinThreads>
  </PropertyGroup>

</Project>

Máximo de subprocesos

  • Especifica el número máximo de subprocesos para el grupo de subprocesos de trabajo.
  • Corresponde al método ThreadPool.SetMaxThreads.
Nombre de valor Valores
runtimeconfig.json System.Threading.ThreadPool.MaxThreads Entero que representa el número máximo de subprocesos.
Propiedad de MSBuild ThreadPoolMaxThreads Entero que representa el número máximo de subprocesos.
Variable del entorno N/D N/D

Ejemplos

Archivo runtimeconfig.json:

{
   "runtimeOptions": {
      "configProperties": {
         "System.Threading.ThreadPool.MaxThreads": 20
      }
   }
}

archivo runtimeconfig.template.json:

{
   "configProperties": {
      "System.Threading.ThreadPool.MaxThreads": 20
   }
}

Archivo del proyecto:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <ThreadPoolMaxThreads>20</ThreadPoolMaxThreads>
  </PropertyGroup>

</Project>

Grupo de subprocesos de Windows

  • Para proyectos en Windows, configura si la administración de subprocesos del grupo de subprocesos se delega al grupo de subprocesos de Windows.
  • Si omite esta configuración o la plataforma no es Windows, se usa en su lugar el grupo de subprocesos de .NET.
  • Solo las aplicaciones publicadas con AOT nativo en Windows usan el grupo de subprocesos de Windows de forma predeterminada, para lo cual puede optar por usar el grupo de subprocesos de .NET en su lugar deshabilitando la configuración.
  • El grupo de subprocesos de Windows puede funcionar mejor en algunos casos, como en los casos en los que el número mínimo de subprocesos está configurado en un valor alto o cuando la aplicación ya usa mucho el grupo de subprocesos de Windows. También puede haber casos en los que el grupo de subprocesos de .NET funcione mejor, como en el control de E/S pesado en máquinas más grandes. Es aconsejable comprobar las métricas de rendimiento al cambiar esta configuración.
  • Algunas API no se admiten al usar el grupo de subprocesos de Windows, como ThreadPool.SetMinThreads, ThreadPool.SetMaxThreads y ThreadPool.BindHandle(SafeHandle). Los valores de configuración del grupo de subprocesos para subprocesos mínimos y máximos tampoco son efectivos. Una alternativa a ThreadPool.BindHandle(SafeHandle) es la clase ThreadPoolBoundHandle.
Nombre de valor Valores Versión introducida
runtimeconfig.json System.Threading.ThreadPool.UseWindowsThreadPool true: habilitado.
false: deshabilitado.
.NET 8
Propiedad de MSBuild UseWindowsThreadPool true: habilitado.
false: deshabilitado.
.NET 8
Variable del entorno DOTNET_ThreadPool_UseWindowsThreadPool 1: habilitado.
0: deshabilitado.
.NET 8

Ejemplos

Archivo runtimeconfig.json:

{
   "runtimeOptions": {
      "configProperties": {
         "System.Threading.ThreadPool.UseWindowsThreadPool": true
      }
   }
}

archivo runtimeconfig.template.json:

{
   "configProperties": {
      "System.Threading.ThreadPool.UseWindowsThreadPool": true
   }
}

Archivo del proyecto:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <UseWindowsThreadPool>true</UseWindowsThreadPool>
  </PropertyGroup>

</Project>

Inserción de subprocesos en respuesta al bloqueo de elementos de trabajo

En algunos casos, el grupo de subprocesos detecta elementos de trabajo que bloquean sus subprocesos. Para compensarlo, inserta más subprocesos. En .NET 6 y versiones posteriores, puede usar las opciones siguientes de configuración del entorno de ejecución para configurar la inserción de subprocesos en respuesta al bloqueo de elementos de trabajo. Actualmente, esta configuración solo surte efecto para los elementos de trabajo que esperan a que se complete otra tarea, como en los casos típicos de sincrónico sobre asincrónico.

Nombre de la opción de configuración runtimeconfig.json Descripción Versión introducida
System.Threading.ThreadPool.Blocking.ThreadsToAddWithoutDelay_ProcCountFactor Una vez alcanzado el recuento de subprocesos basado en MinThreads, este valor (una vez multiplicado por el número de procesadores) especifica cuántos subprocesos adicionales se pueden crear sin retraso. .NET 6
System.Threading.ThreadPool.Blocking.ThreadsPerDelayStep_ProcCountFactor Una vez alcanzado el recuento de subprocesos basado en ThreadsToAddWithoutDelay, este valor (una vez multiplicado por el número de procesadores) especifica después de cuántos subprocesos se agregaría un DelayStepMs adicional al retraso antes de crear cada nuevo hilo. .NET 6
System.Threading.ThreadPool.Blocking.DelayStepMs Una vez alcanzado el recuento de subprocesos basado en ThreadsToAddWithoutDelay, este valor especifica cuánto retraso adicional se agrega por cada ThreadsPerDelayStep subprocesos, que se aplicaría antes de crear cada nuevo subproceso. .NET 6
System.Threading.ThreadPool.Blocking.MaxDelayMs Una vez alcanzado el número de subprocesos basado en ThreadsToAddWithoutDelay, este valor especifica el retraso máximo que se debe usar antes de crear cada subproceso nuevo. .NET 6
System.Threading.ThreadPool.Blocking.IgnoreMemoryUsage De forma predeterminada, la tasa de inserción de subprocesos en respuesta al bloqueo está limitada por heurística que determina si hay suficiente memoria física disponible. En algunas situaciones, puede ser preferible insertar subprocesos más rápidamente incluso en situaciones de poca memoria. Puede deshabilitar la heurística de uso de memoria desactivando este conmutador. .NET 7

Cómo surten efecto las opciones de configuración

  • Una vez alcanzado el número de subprocesos basado en MinThreads, se pueden crear hasta ThreadsToAddWithoutDelay subprocesos adicionales sin retraso.
  • Después, antes de que se cree cada subproceso adicional, se induce un retraso, empezando por DelayStepMs.
  • Por cada ThreadsPerDelayStep subprocesos que se agregan con un retraso, se agrega un DelayStepMs adicional al retraso.
  • El retraso no puede superar MaxDelayMs.
  • Los retrasos solo se inducen antes de crear subprocesos. Si los subprocesos ya están disponibles, se liberarían sin retraso para compensar el bloqueo de elementos de trabajo.
  • También se utiliza el uso y los límites de la memoria física y, más allá de un umbral, el sistema cambia a una inserción de subprocesos más lenta.

Ejemplos

Archivo runtimeconfig.json:

{
   "runtimeOptions": {
      "configProperties": {
         "System.Threading.ThreadPool.Blocking.ThreadsToAddWithoutDelay_ProcCountFactor": 5
      }
   }
}

archivo runtimeconfig.template.json:

{
   "configProperties": {
      "System.Threading.ThreadPool.Blocking.ThreadsToAddWithoutDelay_ProcCountFactor": 5
   }
}

AutoreleasePool para subprocesos administrados

Esta opción configura si cada subproceso administrado recibe un elemento NSAutoreleasePool implícito cuando se ejecuta en una plataforma macOS compatible.

Nombre de valor Valores Versión introducida
runtimeconfig.json System.Threading.Thread.EnableAutoreleasePool true o false .NET 6
Propiedad de MSBuild AutoreleasePoolSupport true o false .NET 6
Variable del entorno N/D N/D N/D

Ejemplos

Archivo runtimeconfig.json:

{
   "runtimeOptions": {
      "configProperties": {
         "System.Threading.Thread.EnableAutoreleasePool": true
      }
   }
}

archivo runtimeconfig.template.json:

{
   "configProperties": {
      "System.Threading.Thread.EnableAutoreleasePool": true
   }
}

Archivo del proyecto:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <AutoreleasePoolSupport>true</AutoreleasePoolSupport>
  </PropertyGroup>

</Project>