本文详细介绍了可用于在 .NET 中配置线程处理的设置。
在 Windows 上使用所有 CPU 组
- 在具有多个 CPU 组的计算机上,此设置将配置线程池等组件是使用所有 CPU 组还是仅使用进程的主 CPU 组。 该设置还会影响返回的内容 Environment.ProcessorCount 。
- 启用此设置后,将使用所有 CPU 组,并且默认情况下线程也会 自动分布在 CPU 组中 。
- 此设置默认在 Windows 11 及更高版本上启用,默认情况下在 Windows 10 及更低版本上禁用。 为了使此设置在启用时生效,还必须将 GC 配置为使用所有 CPU 组;有关详细信息,请参阅 GC CPU 组。
| 设置名称 | 价值观 | |
|---|---|---|
| runtimeconfig.json | N/A | N/A |
| 环境变量 | DOTNET_Thread_UseAllCpuGroups |
0 - 禁用1 - 启用 |
将线程分配到 Windows 上的 CPU 组
- 在使用多个 CPU 组和 所有 CPU 组的计算机上,此设置将配置线程是否自动分布在 CPU 组中。
- 启用此设置后,新线程会以尝试在使用新 CPU 组之前完全填充已使用的 CPU 组的方式分配给 CPU 组。
- 默认情况下,此设置处于启用状态。
| 设置名称 | 价值观 | |
|---|---|---|
| runtimeconfig.json | N/A | N/A |
| 环境变量 | DOTNET_Thread_AssignCpuGroups |
0 - 禁用1 - 启用 |
最小线程数
- 指定工作线程池的最小线程数。
- 对应于 ThreadPool.SetMinThreads 该方法。
| 设置名称 | 价值观 | |
|---|---|---|
| runtimeconfig.json | System.Threading.ThreadPool.MinThreads |
表示最小线程数的整数 |
| MSBuild 属性 | ThreadPoolMinThreads |
表示最小线程数的整数 |
| 环境变量 | N/A | N/A |
例子
runtimeconfig.json 文件:
{
"runtimeOptions": {
"configProperties": {
"System.Threading.ThreadPool.MinThreads": 4
}
}
}
runtimeconfig.template.json 文件:
{
"configProperties": {
"System.Threading.ThreadPool.MinThreads": 4
}
}
项目文件:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ThreadPoolMinThreads>4</ThreadPoolMinThreads>
</PropertyGroup>
</Project>
最大线程数
- 指定工作线程池的最大线程数。
- 对应于 ThreadPool.SetMaxThreads 该方法。
| 设置名称 | 价值观 | |
|---|---|---|
| runtimeconfig.json | System.Threading.ThreadPool.MaxThreads |
表示最大线程数的整数 |
| MSBuild 属性 | ThreadPoolMaxThreads |
表示最大线程数的整数 |
| 环境变量 | N/A | N/A |
例子
runtimeconfig.json 文件:
{
"runtimeOptions": {
"configProperties": {
"System.Threading.ThreadPool.MaxThreads": 20
}
}
}
runtimeconfig.template.json 文件:
{
"configProperties": {
"System.Threading.ThreadPool.MaxThreads": 20
}
}
项目文件:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ThreadPoolMaxThreads>20</ThreadPoolMaxThreads>
</PropertyGroup>
</Project>
Windows 线程池
- 对于 Windows 上的项目,配置线程池线程管理是否委托给 Windows 线程池。
- 如果省略此设置或平台不是 Windows,则改用 .NET 线程池。
- 默认情况下,只有使用 Windows 上的本机 AOT 发布的应用程序使用 Windows 线程池,你可以选择改用 .NET 线程池,方法是禁用配置设置。
- 在某些情况下,Windows 线程池的性能可能更好,例如,如果将最小线程数配置为高值,或者当应用大量使用 Windows 线程池时。 在某些情况下,.NET 线程池的性能更好,例如在较大的计算机上执行大量 I/O 处理。 建议在更改此配置设置时检查性能指标。
- 使用 Windows 线程池(例如 ThreadPool.SetMinThreads, ThreadPool.SetMaxThreads和 ThreadPool.BindHandle(SafeHandle))时不支持某些 API。 最小和最大线程的线程池配置设置也无效。 类的替代 ThreadPool.BindHandle(SafeHandle) 方法 ThreadPoolBoundHandle 。
| 设置名称 | 价值观 | 引入的版本 | |
|---|---|---|---|
| runtimeconfig.json | System.Threading.ThreadPool.UseWindowsThreadPool |
true - 启用false - 禁用 |
.NET 8 |
| MSBuild 属性 | UseWindowsThreadPool |
true - 启用false - 禁用 |
.NET 8 |
| 环境变量 | DOTNET_ThreadPool_UseWindowsThreadPool |
1 - 启用0 - 禁用 |
.NET 8 |
例子
runtimeconfig.json 文件:
{
"runtimeOptions": {
"configProperties": {
"System.Threading.ThreadPool.UseWindowsThreadPool": true
}
}
}
runtimeconfig.template.json 文件:
{
"configProperties": {
"System.Threading.ThreadPool.UseWindowsThreadPool": true
}
}
项目文件:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<UseWindowsThreadPool>true</UseWindowsThreadPool>
</PropertyGroup>
</Project>
线程注入以响应阻止工作项
在某些情况下,线程池会检测阻止其线程的工作项。 为了进行补偿,它会注入更多线程。 在 .NET 6+ 中,可以使用以下 运行时配置 设置来配置线程注入,以响应阻止工作项。 目前,这些设置仅对等待其他任务完成的工作项生效,例如在典型的 同步过度同步 情况下。
| runtimeconfig.json 设置名称 | Description | 引入的版本 |
|---|---|---|
System.Threading.ThreadPool.Blocking.ThreadsToAddWithoutDelay_ProcCountFactor |
在达到基于 MinThreads 线程计数之后,此值(乘以处理器计数后)指定可以创建多少个额外的线程,而不会延迟。 |
.NET 6 |
System.Threading.ThreadPool.Blocking.ThreadsPerDelayStep_ProcCountFactor |
在达到基于 ThreadsToAddWithoutDelay 线程计数之后,此值(乘以处理器计数后)指定在创建每个新线程之前将额外 DelayStepMs 添加到延迟的线程数之后。 |
.NET 6 |
System.Threading.ThreadPool.Blocking.DelayStepMs |
达到基于 ThreadsToAddWithoutDelay 线程计数后,此值指定为每个线程添加 ThreadsPerDelayStep 的额外延迟,这些延迟将在创建每个新线程之前应用。 |
.NET 6 |
System.Threading.ThreadPool.Blocking.MaxDelayMs |
在达到线程 ThreadsToAddWithoutDelay 计数后,此值指定在创建新线程之前使用的最大延迟。 |
.NET 6 |
System.Threading.ThreadPool.Blocking.IgnoreMemoryUsage |
默认情况下,响应阻塞的线程注入速率受启发式限制,以确定是否有足够的物理内存可用。 在某些情况下,即使在内存不足的情况下,也最好更快地注入线程。 可以通过关闭此开关来禁用内存使用情况启发式。 | .NET 7 |
配置设置如何生效
- 在达到线程
MinThreads计数后,ThreadsToAddWithoutDelay最多可以创建额外的线程,而不会延迟。 - 之后,在创建每个附加线程之前,首先会引发
DelayStepMs延迟。 - 对于延迟添加的每个
ThreadsPerDelayStep线程,都会向延迟添加一个额外的DelayStepMs线程。 - 延迟可能不超过
MaxDelayMs。 - 只有在创建线程之前才会引发延迟。 如果线程已可用,则会在不延迟的情况下释放它们,以补偿阻止工作项。
- 还会使用物理内存使用情况和限制,并且超出阈值,系统切换到线程注入速度较慢。
例子
runtimeconfig.json 文件:
{
"runtimeOptions": {
"configProperties": {
"System.Threading.ThreadPool.Blocking.ThreadsToAddWithoutDelay_ProcCountFactor": 5
}
}
}
runtimeconfig.template.json 文件:
{
"configProperties": {
"System.Threading.ThreadPool.Blocking.ThreadsToAddWithoutDelay_ProcCountFactor": 5
}
}
AutoreleasePool 用于托管线程
此选项配置每个托管线程在受支持的 macOS 平台上运行时是否接收隐式 NSAutoreleasePool 。
| 设置名称 | 价值观 | 引入的版本 | |
|---|---|---|---|
| runtimeconfig.json | System.Threading.Thread.EnableAutoreleasePool |
true 或 false |
.NET 6 |
| MSBuild 属性 | AutoreleasePoolSupport |
true 或 false |
.NET 6 |
| 环境变量 | N/A | N/A | N/A |
例子
runtimeconfig.json 文件:
{
"runtimeOptions": {
"configProperties": {
"System.Threading.Thread.EnableAutoreleasePool": true
}
}
}
runtimeconfig.template.json 文件:
{
"configProperties": {
"System.Threading.Thread.EnableAutoreleasePool": true
}
}
项目文件:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AutoreleasePoolSupport>true</AutoreleasePoolSupport>
</PropertyGroup>
</Project>