[英]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.