ThreadPool线程何时释放回线程池?附.NET示例分析
线程池线程何时被释放回线程池?
我想弄清楚ThreadPool线程究竟何时会被释放回ThreadPool,以下是示例程序:
public static async Task Main() { Console.WriteLine("Start"); var t1 = ShortWork("SW1"); var t2 = ShortWork("SW2"); await Task.Delay(50); var t3 = LongWork("LW1"); Console.WriteLine($"After starting LongWork Thread={Thread.CurrentThread.ManagedThreadId}"); await Task.WhenAll(t1, t2); await t3; Console.WriteLine("Done"); } public static async Task ShortWork(string name) { Console.WriteLine($"SHORT Start {name} Thread={Thread.CurrentThread.ManagedThreadId}"); await Task.Delay(500); Console.WriteLine($"SHORT End {name} Thread={Thread.CurrentThread.ManagedThreadId}"); } public static async Task LongWork(string name) { Console.WriteLine($"LONG Start {name} Thread={Thread.CurrentThread.ManagedThreadId}"); await Task.Delay(2500); Console.WriteLine($"LONG End {name} Thread={Thread.CurrentThread.ManagedThreadId}"); }
输出结果:
Start SHORT Start SW1 Thread=1 SHORT Start SW2 Thread=1 LONG Start LW1 Thread=5 After starting LongWork Thread=5 SHORT End SW1 Thread=7 SHORT End SW2 Thread=5 LONG End LW1 Thread=5 Done
从输出能看到,LongWork启动于线程5,之后线程5又承接了ShortWork SW2的结束逻辑,说明线程5曾被释放回线程池。我的疑问是:在LongWork中的await Task.Delay(2500)之后,线程5究竟何时被释放回ThreadPool?是不是调用await时就释放?我觉得不是,因为调用LongWork后立即打印线程ID时,还是在线程5上。那是不是在线程5上调用await Task.WhenAll后,控制权回到Main的上层,线程5因为没有可返回的调用方,此时才被释放?
我自己对流程的理解如下:
- 程序启动于线程1,线程1执行ShortWork SW1和SW2。
- 等待
Task.Delay(50)时,线程1被释放(因为没有更多工作可做)。 - 线程5被选中承接50ms延迟后的续行逻辑。
- 线程5启动
LongWork,执行到await 2500ms延迟处,控制权回到Main,仍在线程5上。等待t1和t2时,控制权回到调用Main的上层,线程5的工作完成,被释放回ThreadPool。 - 此时没有线程在执行任务。
- 当ShortWork的延迟结束后,从线程池中选中线程5和7来承接各自的续行逻辑,完成后这些线程被释放回线程池。
- 另一个线程承接
Task.WhenAll和await t3之间的续行逻辑,随后因只需等待t3而立即被释放。 - 从ThreadPool中选择一个线程承接
LongWork的续行逻辑。 - 最后,一个ThreadPool线程承接
t3完成后输出“Done”的工作。
另外还有一个额外问题:为何线程5承接SW2的结束逻辑,线程7承接SW1的结束逻辑?这些刚被使用过的线程,是否作为“热线程”被优先用于后续续行逻辑?
内容的提问来源于stack exchange,提问作者Eza
相关产品推荐
相关产品推荐

