C# 中的并发与多线程:.NET 开发人员完全指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C# 中的并发与多线程:从 Thread 到 async/await



现代应用程序越来越需要同时执行多个任务:从 Web 服务器处理请求到桌面程序中的并行计算。在 C# (.NET) 中,为此提供了强大的工具集——从经典的线程 (Thread) 到高级别的 async/await 结构和 Task Parallel Library (TPL) 库。在本文中,我们将分析并发和多线程的关键概念、它们的实际应用以及最佳实践。



什么是并发与多线程?



在进入代码之前,理解这些概念之间的区别很重要:



  • 并发 (Concurrency) — 程序通过切换任务来执行多个任务的能力,造成同时执行的假象。这也可以在单核处理器上实现。
  • 多线程 (Multithreading) — 并发的一种形式,其中多个线程 (threads) 在多核处理器上物理上同时执行。
  • 并行 (Parallelism) — 多线程的一个子集,其中任务的不同部分严格同时在不同的内核上执行。


在 C# 中,您既可以使用底层线程,也可以使用自动管理线程的抽象。选择取决于任务:对于 I/O-bound 操作(文件、网络工作),async/await 更合适;而对于 CPU-bound 操作(计算),则使用 Parallel.For 或 Task。



创建和管理线程:Thread 类



System.Threading.Thread 类是 C# 中处理线程的最底层方式。它提供了完全的控制,但需要仔细的同步。



using System;using System.Threading;

class Program{ static void Main() { Thread thread = new Thread(DoWork); thread.Start();

// 主线程继续工作 for (int i = 0; i < 5; i++) { Console.WriteLine($"主线程: {i}"); Thread.Sleep(100); }

thread.Join(); // 等待子线程完成 Console.WriteLine("工作完成。"); }

static void DoWork() { for (int i = 0; i < 5; i++) { Console.WriteLine($"子线程: {i}"); Thread.Sleep(150); } }}


手动管理线程的问题:

  • 同步复杂(数据竞争、死锁)。
  • 创建和销毁线程的开销很高。
  • 缺乏对返回结果的内置支持。


因此,在现代 C# 中,更倾向于使用 Task Parallel Library。



Task Parallel Library (TPL) 与 async/await



来自 System.Threading.Tasks 命名空间的 Task 类代表一个异步操作。结合关键字 async 和 await,它允许编写看起来像同步代码的异步代码。



Task 基础示例



using System;using System.Threading.Tasks;

class Program{ static async Task Main() { Console.WriteLine("开始工作。");

// 启动一个异步任务 Task<int> task = CalculateAsync(10);

// 在任务执行期间,我们可以做其他事情 Console.WriteLine("正在做其他工作...");

// 等待结果 int result = await task; Console.WriteLine($"结果: {result}"); }

static async Task<int> CalculateAsync(int number) { await Task.Delay(1000); // 模拟耗时操作 return number * number; }}

博客

书籍推荐