【问题标题】:Is background thread only executed when the number of foreground threads executing is smaller than the number of processors?是否只有在执行的前台线程数小于处理器数时才执行后台线程?
【发布时间】:2018-11-15 23:18:11
【问题描述】:

根据 docs.microsoft.com [1234]:

只有在执行的前台线程数小于处理器数时,才会执行后台线程。

但是,如果我在 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%.
...

这个陈述是错误的还是我完全理解错了?

【问题讨论】:

  • MSDN 文档完全是错误的。它没有给出“前台”与“后台”线程的定义。就操作系统而言,前台线程是具有用户正在与之交互的窗口的线程。它确实获得了更大的线程量。
  • 这会是带有超线程的 4 核 Intel 吗?这将在这 4 个内核上为您提供 8 个线程。也许用 8 而不是 4 再试一次...
  • @Patrick Hughes,没有超线程,编辑了问题,谢谢。

标签: c# .net multithreading clr


【解决方案1】:

在我看来,该声明是不正确的,此外,您查看的不是最新版本的文档。如果您查找关于Managed Threading / Foreground and Background Threads最新版本的文档,它会指出:

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

    注意

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

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

【讨论】:

  • 文档几乎不老:英文文档的最新版本(2018 年 10 月 15 日)指的是包含引用片段的文章,the version of documentation before that(2018 年 4 月 5 日)包含确切的内容引用片段,最新版本的法语、德语和俄语文档(2017 年 11 月 30 日)都包含引用片段。
  • @A.Milto:您提供的问题中的 3 个链接参考了框架的旧版本(1.1、3.0、4.0)。您评论中的链接引用了 2017 年底的来源(通过 web.archive.org),同样的 original link 已经更新。还要考虑到文档不会每天更新 - 他们只是将它们迁移到 docs.microsoft.com(可能更新了时间戳)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多