c# - 为什么我的 ThreadID 对于 10 个并行运行的任务来说不是唯一的?

标签 c# .net multithreading

我的代码将 10 个“作业”放入队列中,显示它们的线程 ID,然后立即开始并行运行。我知道作业是并行运行的,因为每个作业只是延迟 20 秒,而所有 10 个作业都在 20 秒内完成。令我困惑的是,有几个重复的 ThreadID,据推测每个线程都应该有一个唯一的 ID,这是我读过的。这怎么可能?是否存在重复项,因为重复项可能在不同的处理器内核上(如果是这样,这就不太好了,因为最终我希望能够使用其线程 ID 取消任务)?

这是在我的控制台窗口中显示的线程 ID 列表”

线程 ID:10 线程 ID:11 线程 ID:11 线程 ID:12 线程 ID:13 线程 ID:14 线程 ID:15 线程 ID:16 线程 ID:6 线程 ID:6

我尽可能地简化了代码,并计算了程序完成所需的时间。

这是一个控制台应用程序

class Program
{

    private static Object lockObj = new Object();

    static void Main(string[] args)
    {
        var q = new TPLDataflowMultipleHandlers();
        var numbers = Enumerable.Range(1, 10);

        Console.Clear();

        foreach (var num in numbers)
        {
            q.Enqueue(num.ToString());
        }
        Console.ReadLine();
    }
} // end of program class


public class TPLDataflowMultipleHandlers
{
    private static Object lockObj = new Object();

    private ActionBlock<string> _jobs;

    public TPLDataflowMultipleHandlers()
    {
        var executionDataflowBlockOptions = new ExecutionDataflowBlockOptions()
        {
            MaxDegreeOfParallelism = 16,
        };

        _jobs = new ActionBlock<string>(async (job) =>
       {
           ShowThreadInformation("Main Task(Task #" + Task.CurrentId.ToString() + ")");
           Console.WriteLine($"STARTING job:{job},  thread: { Thread.CurrentThread.ManagedThreadId}");

           await Task.Delay(20000);

           Console.WriteLine($"FINISHED job:{job},  thread: { Thread.CurrentThread.ManagedThreadId}");
       }, executionDataflowBlockOptions);
    }

    public void Enqueue(string job)
    {
        _jobs.Post(job);
    }

    private static void ShowThreadInformation(String taskName)
    {
        String msg = null;
        Thread thread = Thread.CurrentThread;
        lock (lockObj)
        {
            msg = String.Format("{0} thread information\n", taskName) +
                  String.Format("   Background: {0}\n", thread.IsBackground) +
                  String.Format("   Thread Pool: {0}\n", thread.IsThreadPoolThread) +
                  String.Format("   Thread ID: {0}\n", thread.ManagedThreadId);
        }
        Console.WriteLine(msg);
    }
}

我完全期待 10 个唯一的线程 ID 号。

最佳答案

线程和任务不是一回事 - 将 Thread 视为工作人员,将 Task 视为要执行的一项工作。仅仅因为您创建了 10 件需要完成的事情并不意味着您需要 10 个工作人员来完成它们 - 如果您已经拥有 4 个工作人员(工作线程的默认数量在 . NET ThreadPool) 开始执行工作单元,只有在现有工作单元似乎跟不上时才会创建新工作单元 (Threads)。您在代码中创建的每个“工作单元”都非常短,因此它的执行速度非常快,执行它的同一线程变得空闲并运行另一个在后台队列中等待的线程。

如果您想看到它的实际效果,只需将类似 Thread.Sleep(30000) 的内容放在您的 ShowThreadInformation 中。这将导致您的任务的执行时间人为变长,并且 .NET 线程池会注意到队列中的任务不足,并启动新线程来执行它们。

看这里 - What is the difference between task and thread?

关于c# - 为什么我的 ThreadID 对于 10 个并行运行的任务来说不是唯一的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58664723/

相关文章:

c# - 检测未具体化的 LINQ 查询

java - Java 线程转储中缺少线程

python - 时间特定线程

c# - 在另一个项目 c# 中使用引用项目的 WCF 服务

c# - 无法启动服务。服务进程无法连接到服务 Controller

java - 自定义 future 对象

c# - 如何使用 LINQ 从 IEnumerable 中选择随机项

C# 无法捕获 SerializationException

c# - 如何在 C# 中的这种奇怪情况下创建通用列表

c# - 在 Parallel.ForEach 中指定默认的 MaxDegreeOfParallelism?