c# - 是否只有在执行的前台线程数小于处理器数时才执行后台线程?
问题描述
根据docs.microsoft.com [ 1、2、3、4 ]:_ _ _
仅当执行的前台线程数小于处理器数时,才会执行后台线程。
但是,如果我在 4 核 CPU(无超线程)上启动 4 个前台线程,然后启动 4 个后台线程,则前台线程和后台线程将并行运行,这似乎与上面的说法相矛盾。
代码示例:
static void Main(string[] args)
{
int numberOfProcessors = 4;
for (int i = 0; i < numberOfProcessors; i++)
{
int threadNumber = i;
new Thread(() =>
{
Console.WriteLine($"Foreground thread {threadNumber} started.");
for (int j = 1; j <= 100; j++)
{
for (long k = 0; k < 10000000000; k++);
Console.WriteLine($"Foreground thread {threadNumber} progress: {j}%.");
}
})
.Start();
}
for (int i = 0; i < numberOfProcessors; i++)
{
int threadNumber = i;
var backgroundThread = new Thread(() =>
{
Console.WriteLine($"Background thread {threadNumber} started.");
for (int j = 1; j <= 100; j++)
{
for (long k = 0; k < 10000000000; k++);
Console.WriteLine($"Background thread {threadNumber} progress: {j}%.");
}
});
backgroundThread.IsBackground = true;
backgroundThread.Start();
}
Console.ReadLine();
}
输出:
Foreground thread 1 started.
Foreground thread 0 started.
Foreground thread 3 started.
Foreground thread 2 started.
Background thread 0 started.
Background thread 1 started.
Background thread 2 started.
Background thread 3 started.
Foreground thread 2 progress: 1%.
Foreground thread 0 progress: 1%.
Foreground thread 1 progress: 1%.
Foreground thread 3 progress: 1%.
Background thread 1 progress: 1%.
Background thread 0 progress: 1%.
Background thread 2 progress: 1%.
Background thread 3 progress: 1%.
Foreground thread 0 progress: 2%.
Foreground thread 2 progress: 2%.
Foreground thread 1 progress: 2%.
Foreground thread 3 progress: 2%.
Background thread 0 progress: 2%.
Background thread 1 progress: 2%.
Background thread 3 progress: 2%.
Background thread 2 progress: 2%.
Foreground thread 0 progress: 3%.
Foreground thread 2 progress: 3%.
Foreground thread 1 progress: 3%.
Foreground thread 3 progress: 3%.
Background thread 1 progress: 3%.
Background thread 0 progress: 3%.
Background thread 3 progress: 3%.
Background thread 2 progress: 3%.
...
陈述是不正确的还是我只是弄错了?
解决方案
在我看来,该声明是不正确的,此外,您查看的不是最新版本的文档。如果您查找有关托管线程/前台和后台线程的文档的最新版本,它会指出:
托管线程要么是后台线程,要么是前台线程。后台线程与前台线程相同,但有一个例外:后台线程不会使托管执行环境保持运行。一旦托管进程中的所有前台线程都已停止(其中 .exe 文件是托管程序集),系统将停止所有后台线程并关闭。
笔记
当运行时因为进程正在关闭而停止后台线程时,线程中不会引发异常。但是,当线程因 AppDomain.Unload 方法卸载应用程序域而停止时,前台和后台线程都会引发 ThreadAbortException。
使用 Thread.IsBackground 属性来确定线程是后台线程还是前台线程,或者更改其状态。通过将其 IsBackground 属性设置为 true,可以随时将线程更改为后台线程。
重要的
线程的前台或后台状态不会影响线程中未处理异常的结果。在 .NET Framework 2.0 版中,前台或后台线程中的未处理异常会导致应用程序终止。请参阅托管线程中的异常。
属于托管线程池的线程(即 IsThreadPoolThread 属性为 true 的线程)是后台线程。从非托管代码进入托管执行环境的所有线程都被标记为后台线程。通过创建和启动一个新的 Thread 对象生成的所有线程默认都是前台线程。
如果您使用线程来监视活动,例如套接字连接,请将其 IsBackground 属性设置为 true,以便线程不会阻止您的进程终止。
Thread.IsBackground属性
的文档也是如此:
评论
线程要么是后台线程,要么是前台线程。后台线程与前台线程相同,只是后台线程不会阻止进程终止。一旦属于一个进程的所有前台线程都已终止,公共语言运行时就会结束该进程。任何剩余的后台线程都将停止并且不会完成。
默认情况下,以下线程在前台执行(即它们的 IsBackground 属性返回 false):
- 主线程(或主应用程序线程)。
- 通过调用 Thread 类构造函数创建的所有线程。
默认情况下,以下线程在后台执行(即,它们的 IsBackground 属性返回 true):
线程池线程,这是运行时维护的工作线程池。您可以使用 ThreadPool 类配置线程池并安排线程池线程上的工作。
笔记
基于任务的异步操作自动在线程池线程上执行。
从非托管代码进入托管执行环境的所有线程。
推荐阅读
- json - 在 JSON 中以不同的顺序连接来自名称/值数据的字符串
- sql - 如何使用查询在不同列中找到相同值的出现
- python - 在 Python 中插入主目录的问题
- android - Arch Linux 上的 Genymotion:启动时虚拟设备立即消失
- java - 如何在不崩溃的情况下提取 JSON 信息?
- c++ - C++ curl_easy_perform() 在响应中插入换行符
- javascript - 我将如何在 highcharts 中填充 MAX MIN 项目符号?
- c# - 重用而不从接口转换为类
- java - jQuery。码头:跨域请求
- javascript - 从另一个 ejs 文件加载变量的简单方法?