概述
线程池(ThreadPool)和 Task 是 .NET 中推荐的并发编程方式。它们简化了线程管理,避免频繁创建销毁线程的开销。
线程池 (ThreadPool)
线程池维护一组工作线程,任务到来时分配空闲线程执行。
基础使用
1 2 3 4 5 6 7 8 9 10 11 12
| using System.Threading;
ThreadPool.QueueUserWorkItem(state => { Console.WriteLine($"线程池执行,线程 ID: {Thread.CurrentThread.ManagedThreadId}"); });
ThreadPool.QueueUserWorkItem(state => { int data = (int)state; Console.WriteLine($"数据: {data}"); }, 42);
|
设置线程池大小
1 2 3 4 5 6 7 8
| ThreadPool.GetMinThreads(out int minWorker, out int minIo); ThreadPool.GetMaxThreads(out int maxWorker, out int maxIo); Console.WriteLine($"最小工蜂线程: {minWorker}, 最小 IO 线程: {minIo}");
ThreadPool.SetMinThreads(4, 4); ThreadPool.SetMaxThreads(50, 50);
|
Task(推荐)
Task 基于线程池,提供更丰富的 API。
创建和启动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| using System.Threading.Tasks;
Task task1 = Task.Run(() => { Console.WriteLine("Task 执行"); });
Task task2 = Task.Factory.StartNew(() => { Console.WriteLine("Factory 创建"); });
Task<int> taskWithResult = Task.Run(() => { return 42; }); int result = await taskWithResult;
|
等待完成
1 2 3 4 5 6 7 8 9 10 11 12
| Task task = Task.Run(() => Thread.Sleep(1000));
task.Wait();
bool completed = task.Wait(TimeSpan.FromSeconds(2));
Task[] tasks = { task1, task2 }; Task.WaitAll(tasks); Task.WaitAny(tasks);
|
延续 (Continuation)
1 2 3 4 5 6 7 8
| Task.Run(() => 42) .ContinueWith(prev => { Console.WriteLine($"前一个结果: {prev.Result}"); return prev.Result * 2; }) .ContinueWith(prev => { Console.WriteLine($"最终结果: {prev.Result}"); });
|
异常处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| Task task = Task.Run(() => { throw new InvalidOperationException("任务异常"); });
try { await task; } catch (InvalidOperationException ex) { Console.WriteLine($"捕获异常: {ex.Message}"); }
try { task.Wait(); } catch (AggregateException ae) { foreach (var ex in ae.InnerExceptions) { Console.WriteLine(ex.Message); } }
|
取消任务 (CancellationToken)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| using System.Threading;
CancellationTokenSource cts = new CancellationTokenSource();
Task task = Task.Run(() => { while (!cts.Token.IsCancellationRequested) { Console.WriteLine("工作中..."); Thread.Sleep(500); } Console.WriteLine("任务已取消"); }, cts.Token);
Thread.Sleep(2000); cts.Cancel(); await task;
|
带超时的自动取消
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(3));
try { await Task.Run(() => { for (int i = 0; i < 10; i++) { cts.Token.ThrowIfCancellationRequested(); Thread.Sleep(1000); } }, cts.Token); } catch (OperationCanceledException) { Console.WriteLine("任务因超时被取消"); }
|
async/await 配合 Task
1 2 3 4 5 6 7 8 9
| public async Task<string> FetchDataAsync() { await Task.Delay(1000); return "数据"; }
string data = await FetchDataAsync();
|
1 2
| await Task.Delay(1000).ConfigureAwait(false);
|
长时间运行的任务
默认 Task 使用线程池,长时间运行可能阻塞其他任务:
1 2 3 4 5 6 7
| Task longTask = Task.Factory.StartNew(() => { while (true) { } }, TaskCreationOptions.LongRunning);
|
完整示例:批量请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| using System; using System.Collections.Generic; using System.Threading.Tasks;
class Program { static async Task Main() { var urls = new[] { "url1", "url2", "url3", "url4", "url5" }; var tasks = new List<Task<string>>(); foreach (var url in urls) { tasks.Add(DownloadAsync(url)); } string[] results = await Task.WhenAll(tasks); foreach (var result in results) { Console.WriteLine(result); } } static async Task<string> DownloadAsync(string url) { await Task.Delay(500); return $"下载完成: {url}"; } }
|
对比总结
| 特性 |
Thread |
ThreadPool |
Task |
| 创建开销 |
高 |
低 |
极低 |
| 返回值支持 |
无 |
无 |
有 (Task) |
| 取消支持 |
手动 |
手动 |
CancellationToken |
| 异常传播 |
需自行处理 |
需自行处理 |
自动传播 |
| 延续 |
无 |
无 |
ContinueWith / await |
| 推荐度 |
特殊场景 |
中 |
高 |
最佳实践
- 默认使用 Task,除非需要精细化控制线程
- 使用 async/await 编写异步代码
- 始终处理异常,不要静默失败
- 库代码使用 ConfigureAwait(false)
- LongRunning 任务使用 TaskCreationOptions.LongRunning
参考资源