首页 > 解决方案 > 是否只有在执行的前台线程数小于处理器数时才执行后台线程?

问题描述

根据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%.
...

陈述是不正确的还是我只是弄错了?

标签: c#.netmultithreadingclr

解决方案


在我看来,该声明是不正确的,此外,您查看的不是最新版本的文档。如果您查找有关托管线程/前台和后台线程的文档的最新版本,它会指出:

托管线程要么是后台线程,要么是前台线程。后台线程与前台线程相同,但有一个例外:后台线程不会使托管执行环境保持运行。一旦托管进程中的所有前台线程都已停止(其中 .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 类配置线程池并安排线程池线程上的工作。

    笔记

    基于任务的异步操作自动在线程池线程上执行。

  • 从非托管代码进入托管执行环境的所有线程。


推荐阅读