繁体   English   中英

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

[英]Why are my ThreadIDs not unique for 10 tasks running in parallel?

我的代码将 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 )。 您在代码中创建的每个“工作单元”都很短,因此它执行得非常快,执行它的同一线程变得空闲并运行另一个在后台队列中等待的线程。

如果您想看到它的实际效果,只需在ShowThreadInformation中的某处放置类似Thread.Sleep(30000)的东西。 这将导致您的任务的执行被人为地延长,并且 .NET 线程池将注意到任务在队列中被饿死并启动新线程来执行它们。

看看这里 - 任务和线程有什么区别?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM