我的代码将 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 线程池会注意到队列中的任务不足,并启动新线程来执行它们。
关于c# - 为什么我的 ThreadID 对于 10 个并行运行的任务来说不是唯一的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58664723/