Thread最底层但需手动管理生命周期;Task是现代首选,代表异步操作而非线程;Parallel适用于并行循环;共享变量必须线程安全。
Thread 类启动线程最直接,但需手动管理生命周期这是最底层的多线程方式,适合需要精确控制线程启停、优先级或前台/后台属性的场景。创建后必须显式调用 Start(),否则线程不会运行。
Thread 默认是前台线程,主线程退出时它会强制终止;设 IsBackground = true 可改为后台线程Start(),否则抛出 ThreadStateException
Thread,容易耗尽线程池资源var t = new Thread(() => Console.WriteLine("Hello"));
t.IsBackground = true;
t.Start();Task 是现代 C# 多线程首选,自动调度且支持 async/awaitTask 不等于线程——它代表一个异步操作,可能由线程池线程执行,也可能只是 I/O 完成回调,不占用独占线程。
Task.Run(() => {...}) 把 CPU 密集型工作交给线程池,比手建 Thread 更轻量Task.Run 里调用 async 方法却不 await,会导致“fire-and-forget”,异常无法捕获await task 或 task.Result(后者会阻塞,慎用)var task = Task.Run(() => {
Thread.Sleep(1000); // 模拟 CPU 工作
return 42;
});
int result = await task; // 推荐用 awaitParallel.For 和 Parallel.ForEach 更安全当你要对数组或集合做大量独立计算时,它们比手动开多个 Task 更简洁,且内置了分区、取消和异常聚合机制。
Task 实现,但自动处理数据分割和线程协调AggregateException
ParallelOptions.MaxDegreeOfParallelism
Parallel.ForEach(items, new ParallelOptions { MaxDegreeOfParallelism = 4 }, item => {
Process(item);
});多个线程同时读写同一个字段(比如 int counter)会导致值丢失,这不是概率问题,是必然发生。
Interlocked.Increment(ref counter),比 lock 更高效lock(obj),注意锁对象不能是 this、值类型或字符串常量
List 非线程安全;改用 ConcurrentQueue、ConcurrentDictionary 等lock,应改用 AsyncLock 或 SemaphoreSlim.WaitAsync()
真正难的不是启动几个线程,而是判断该不该用线程、用哪种抽象、以及共享状态怎么同步。很多性能问题其实源于误以为“多线程=快”,结果反而因锁争用或上下文切换变得更慢。