Laufzeitkonfigurationsoptionen für das Threading

In diesem Artikel werden die Einstellungen beschrieben, mit denen Sie das Threading in .NET konfigurieren können.

Hinweis

In .NET 6 ist das Präfix DOTNET_ statt COMPlus_ Standard für Umgebungsvariablen, die das .NET-Runtimeverhalten konfigurieren. Das Präfix COMPlus_ funktioniert jedoch weiterhin. Wenn Sie eine frühere Version der .NET-Runtime verwenden, sollten Sie weiterhin das Präfix COMPlus_ für Umgebungsvariablen verwenden.

Verwenden aller CPU-Gruppen unter Windows

  • Auf Computern mit mehreren CPU-Gruppen konfiguriert diese Einstellung, ob Komponenten wie der Threadpool alle CPU-Gruppen oder nur die primäre CPU-Gruppe des Prozesses verwenden. Die Einstellung wirkt sich auch darauf aus, was Environment.ProcessorCount zurückgibt.
  • Wenn diese Einstellung aktiviert ist, werden alle CPU-Gruppen verwendet, und Threads werden ebenfalls standardmäßig automatisch über CPU-Gruppen verteilt.
  • Diese Einstellung ist standardmäßig unter Windows 11 und höheren Versionen aktiviert und standardmäßig unter Windows 10 und früheren Versionen deaktiviert. Damit diese Einstellung wirksam wird, wenn sie aktiviert ist, muss die GC auch so konfiguriert sein, dass alle CPU-Gruppen verwendet werden. Weitere Informationen finden Sie unter CPU-Gruppen für die Garbage Collection.
Einstellungsname Werte
runtimeconfig.json Nicht zutreffend Nicht zutreffend
Umgebungsvariable COMPlus_Thread_UseAllCpuGroups oder DOTNET_Thread_UseAllCpuGroups 0 – deaktiviert
1 – aktiviert

Zuweisen von Threads zu CPU-Gruppen unter Windows

  • Auf Computern mit mehreren CPU-Gruppen und wenn alle CPU-Gruppen verwendet werden, konfiguriert diese Einstellung, ob Threads automatisch über CPU-Gruppen verteilt werden.
  • Wenn diese Einstellung aktiviert ist, werden einer CPU-Gruppe neue Threads auf eine Weise zugewiesen, bei der versucht wird, eine bereits verwendete CPU-Gruppe vollständig aufzufüllen, bevor eine neue CPU-Gruppe verwendet wird.
  • Diese Einstellung ist standardmäßig aktiviert.
Einstellungsname Werte
runtimeconfig.json Nicht zutreffend Nicht zutreffend
Umgebungsvariable COMPlus_Thread_AssignCpuGroups oder DOTNET_Thread_AssignCpuGroups 0 – deaktiviert
1 – aktiviert

Mindestanzahl an Threads

Einstellungsname Werte
runtimeconfig.json System.Threading.ThreadPool.MinThreads Eine ganze Zahl, die die Mindestanzahl an Threads angibt
MSBuild-Eigenschaft ThreadPoolMinThreads Eine ganze Zahl, die die Mindestanzahl an Threads angibt
Umgebungsvariable Nicht zutreffend Nicht zutreffend

Beispiele

runtimeconfig.json-Datei:

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

runtimeconfig.template.json-Datei:

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

Projektdatei:

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

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

</Project>

Maximale Anzahl an Threads

Einstellungsname Werte
runtimeconfig.json System.Threading.ThreadPool.MaxThreads Eine ganze Zahl, die die maximale Anzahl der Threads darstellt
MSBuild-Eigenschaft ThreadPoolMaxThreads Eine ganze Zahl, die die maximale Anzahl der Threads darstellt
Umgebungsvariable Nicht zutreffend Nicht zutreffend

Beispiele

runtimeconfig.json-Datei:

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

runtimeconfig.template.json-Datei:

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

Projektdatei:

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

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

</Project>

Windows-Threadpool

  • Bei Projekten unter Windows wird konfiguriert, ob die Threadverwaltung des Threadpools an den Windows-Threadpool delegiert wird.
  • Wenn Sie diese Einstellung weglassen oder die Plattform nicht Windows ist, wird stattdessen der .NET-Threadpool verwendet.
  • Nur Anwendungen, die mit nativem AOT unter Windows veröffentlicht wurden, verwenden standardmäßig den Windows-Threadpool, für den Sie stattdessen den .NET-Threadpool nutzen können, indem Sie die Konfigurationseinstellung deaktivieren.
  • Der Windows-Threadpool kann in einigen Fällen besser ausgeführt werden, z. B. in Fällen, in denen die Mindestanzahl von Threads auf einen hohen Wert konfiguriert ist, oder wenn der Windows-Threadpool bereits stark von der App verwendet wird. Es kann auch Fälle geben, in denen der .NET-Threadpool besser ausgeführt wird, z. B. bei einer hohen E/A-Verarbeitung auf größeren Computern. Es ist ratsam, Leistungsmetriken beim Ändern dieser Konfigurationseinstellung zu überprüfen.
  • Einige APIs werden nicht unterstützt, wenn Sie den Windows-Threadpool verwenden, z. B. ThreadPool.SetMinThreads, ThreadPool.SetMaxThreads und ThreadPool.BindHandle(SafeHandle). Die Konfigurationseinstellungen des Threadpools für minimale und maximale Threads sind ebenfalls nicht effektiv. Eine Alternative zu ThreadPool.BindHandle(SafeHandle) ist die Klasse ThreadPoolBoundHandle.
Einstellungsname Werte Eingeführt in Version
runtimeconfig.json System.Threading.ThreadPool.UseWindowsThreadPool true – aktiviert
false – deaktiviert
.NET 8
MSBuild-Eigenschaft UseWindowsThreadPool true – aktiviert
false – deaktiviert
.NET 8
Umgebungsvariable DOTNET_ThreadPool_UseWindowsThreadPool 1 – aktiviert
0 – deaktiviert
.NET 8

Beispiele

runtimeconfig.json-Datei:

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

runtimeconfig.template.json-Datei:

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

Projektdatei:

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

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

</Project>

Threadinjektion als Reaktion auf blockierende Arbeitselemente

In einigen Fällen erkennt der Threadpool Arbeitselemente, die seine Threads blockieren. Um dies auszugleichen, fügt er weitere Threads ein. In .NET 6 und höher können Sie die folgenden Einstellungen zur Laufzeitkonfiguration verwenden, um die Threadinjektion als Reaktion auf blockierende Arbeitselemente zu konfigurieren. Derzeit werden diese Einstellungen nur für Arbeitselemente wirksam, die auf den Abschluss einer anderen Aufgabe warten, z. B. in typischen Sync-over-Async-Fällen.

Name der runtimeconfig.json-Einstellung BESCHREIBUNG Eingeführt in Version
System.Threading.ThreadPool.Blocking.ThreadsToAddWithoutDelay_ProcCountFactor Nachdem die Threadanzahl gemäß MinThreads erreicht wurde, gibt dieser Wert (nachdem er mit der Prozessoranzahl multipliziert wurde) an, wie viele zusätzliche Threads ohne Verzögerung erstellt werden können. .NET 6
System.Threading.ThreadPool.Blocking.ThreadsPerDelayStep_ProcCountFactor Nachdem die Threadanzahl gemäß ThreadsToAddWithoutDelay erreicht wurde, gibt dieser Wert (nachdem er mit der Prozessoranzahl multipliziert wurde) an, nach wie vielen Threads der Verzögerung ein weiterer DelayStepMs-Wert hinzugefügt wird, bevor die einzelnen neuen Threads erstellt werden. .NET 6
System.Threading.ThreadPool.Blocking.DelayStepMs Nachdem die Threadanzahl gemäß ThreadsToAddWithoutDelay erreicht wurde, gibt dieser Wert an, wie viel zusätzliche Verzögerung pro ThreadsPerDelayStep-Thread hinzugefügt werden muss und vor dem Erstellen der einzelnen neuen Threads angewendet wird. .NET 6
System.Threading.ThreadPool.Blocking.MaxDelayMs Nachdem die Threadanzahl gemäß ThreadsToAddWithoutDelay erreicht wurde, gibt dieser Wert die maximale Verzögerung an, die vor dem Erstellen der einzelnen neuen Threads angewendet werden soll. .NET 6
System.Threading.ThreadPool.Blocking.IgnoreMemoryUsage Standardmäßig ist die Rate der Threadinjektion als Reaktion auf die Blockierung durch Heuristiken begrenzt. Diese bestimmen, ob genügend physischer Arbeitsspeicher verfügbar ist. In manchen Situationen wird teilweise bevorzugt, Threads auch in Situationen mit geringem Arbeitsspeicher schneller zu injizieren. Sie können die Heuristiken für die Speicherauslastung deaktivieren, indem Sie diese Option deaktivieren. .NET 7

Inkrafttreten der Konfigurationseinstellungen

  • Nachdem die Threadanzahl gemäß MinThreads erreicht wurde, können bis zu ThreadsToAddWithoutDelay zusätzliche Threads ohne Verzögerung erstellt werden.
  • Danach wird vor der Erstellung jedes weiteren Threads eine Verzögerung ausgelöst, beginnend mit DelayStepMs.
  • Für alle ThreadsPerDelayStep-Threads, die mit einer Verzögerung hinzugefügt werden, wird der Verzögerung ein zusätzlicher DelayStepMs-Wert hinzugefügt.
  • Die Verzögerung darf MaxDelayMs nicht überschreiten.
  • Verzögerungen werden nur vor dem Erstellen von Threads ausgelöst. Wenn Threads bereits verfügbar sind, werden sie ohne Verzögerung freigegeben, um blockierende Arbeitselemente auszugleichen.
  • Außerdem werden die Nutzungs- und Grenzwerte für physischen Arbeitsspeicher angewendet, und ab einem bestimmten Schwellenwert wechselt das System zu einer langsameren Threadinjektion.

Beispiele

runtimeconfig.json-Datei:

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

runtimeconfig.template.json-Datei:

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

AutoreleasePool für verwaltete Threads

Mit dieser Option wird konfiguriert, ob jeder verwaltete Thread bei Ausführung auf einer unterstützten macOS-Plattform einen impliziten NSAutoreleasePool empfängt.

Einstellungsname Werte Eingeführt in Version
runtimeconfig.json System.Threading.Thread.EnableAutoreleasePool true oder false .NET 6
MSBuild-Eigenschaft AutoreleasePoolSupport true oder false .NET 6
Umgebungsvariable Nicht zutreffend Nicht zutreffend Nicht zutreffend

Beispiele

runtimeconfig.json-Datei:

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

runtimeconfig.template.json-Datei:

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

Projektdatei:

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

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

</Project>