c# 如何创建线程池

来源:这里教程网 时间:2026-02-21 17:38:28 作者:

ThreadPool.QueueUserWorkItem
提交任务最直接

不需要手动创建“线程池对象”,.NET 的

ThreadPool
是静态类,全局唯一,开箱即用。你只需要把工作项丢进去,运行时自动调度:

ThreadPool.QueueUserWorkItem(_ =>
{
    Console.WriteLine($"Task running on thread: {Thread.CurrentThread.ManagedThreadId}");
});

注意:

QueueUserWorkItem
接收一个
WaitCallback
委托(即
Action<object></object>
),参数是可选的上下文对象。如果不需要传参,用占位符
_
即可。

常见错误:试图 new 一个

ThreadPool
实例 —— 它没有公共构造函数,
new ThreadPool()
编译不通过。

Task.Run
是更现代、推荐的替代方式

虽然底层仍走

ThreadPool
,但
Task.Run
提供了更好的错误传播、取消支持和 async/await 兼容性:

Task.Run(() =>
{
    // 这里执行 CPU 密集型工作
    Thread.Sleep(1000);
    Console.WriteLine("Done");
});

优势对比:

Task.Run
返回
Task
,可 await、可 .ContinueWith、可加
cancellationToken
ThreadPool.QueueUserWorkItem
不返回句柄,异常会直接终止进程(除非捕获在委托内部)
.NET 6+ 中,
Task.Run
默认使用
ThreadPool
,行为一致,但抽象层级更高

需要自定义线程池?基本没必要,但可调
ThreadPool.SetMinThreads

绝大多数场景下,不要试图“创建新线程池”。.NET 的默认线程池已高度优化。真有特殊需求(比如 IO 密集型服务需更快响应),可微调:

int workerThreads, ioThreads;
ThreadPool.GetMinThreads(out workerThreads, out ioThreads);
ThreadPool.SetMinThreads(100, ioThreads); // 至少预留 100 个工作线程

但要注意:

SetMinThreads
影响的是“最小空闲线程数”,不是最大线程数(上限由系统决定)
设得过高会导致内存占用上升、上下文切换开销变大 ASP.NET Core 等托管环境通常禁止调用此 API,会抛出
PlatformNotSupportedException

别混淆:ThreadPool ≠ TaskScheduler.Default ≠ 自定义
TaskScheduler

容易踩坑的地方:

Task.Run
默认用
TaskScheduler.Default
,它背后就是
ThreadPool
—— 二者不是并列关系,而是包装关系
new Thread(...).Start()
是全新线程,不走线程池,开销大,别用来替代
写异步方法时,
await Task.Delay(100)
不消耗线程池线程;但
await Task.Run(() => Thread.Sleep(100))
才真正占用一个池线程

线程池本质是资源复用机制,不是“你要就给你一个新池子”。理解这点,才能避免过度配置或误用

new Thread

相关推荐