.NET基础拾遗(5)多线程开发基础
.NET基础拾遗5多线程开发基础一、多线程概述为什么需要它在.NET开发中多线程是提升应用程序性能和响应能力的关键技术。想象一下一个桌面应用程序在下载文件时如果使用单线程UI会冻结直到下载完成——用户无法操作界面体验极差。多线程允许程序同时执行多个任务比如一个线程处理用户输入另一个线程在后台下载数据第三个线程更新进度条。在.NET中线程是操作系统调度的最小执行单元。每个进程至少有一个主线程而多线程编程就是创建和管理额外的线程来并行工作。但要注意线程不是越多越好——线程切换有开销且访问共享资源时可能引发竞态条件。因此理解基础概念和实践至关重要。### 二、基础概念Thread类与线程生命周期.NET中最基础的多线程类是System.Threading.Thread。它允许你创建、启动、暂停、恢复和终止线程。线程的生命周期包括未启动、运行、阻塞、休眠、终止等状态。#### 2.1 创建和启动线程以下代码展示如何用Thread类创建并启动一个简单线程csharpusing System;using System.Threading;class Program{ static void Main() { // 创建线程对象指定要执行的方法 Thread workerThread new Thread(DoWork); // 设置为后台线程应用程序退出时自动终止 workerThread.IsBackground true; // 启动线程 workerThread.Start(); // 主线程继续执行其他任务 Console.WriteLine(主线程正在运行...); // 等待用户输入防止控制台退出 Console.ReadLine(); } // 线程要执行的方法 static void DoWork() { for (int i 0; i 5; i) { Console.WriteLine($工作线程: 第 {i1} 次循环); // 模拟耗时操作让出CPU给其他线程 Thread.Sleep(500); } Console.WriteLine(工作线程完成。); }}输出示例主线程正在运行...工作线程: 第 1 次循环工作线程: 第 2 次循环工作线程: 第 3 次循环工作线程: 第 4 次循环工作线程: 第 5 次循环工作线程完成。注释说明-Thread.Sleep(500)让当前线程暂停500毫秒模拟耗时工作。-IsBackground true后台线程不会阻止进程退出。如果设为前台线程即使主线程结束进程也会等待该线程完成。- 注意主线程的Console.ReadLine()保证了控制台不会立即关闭否则后台线程可能被强行终止。#### 2.2 线程参数传递与返回值线程方法默认不能直接返回值但可以通过回调或共享变量实现。以下示例展示如何传递参数csharpusing System;using System.Threading;class Program{ static void Main() { // 使用ParameterizedThreadStart传递对象参数 Thread worker new Thread(CalculateSum); worker.Start(10); // 传递一个整数自动装箱为object // 另一种方式使用Lambda表达式推荐 Thread worker2 new Thread(() { int result 0; for (int i 1; i 5; i) result i; Console.WriteLine($Lambda线程计算结果: {result}); }); worker2.Start(); Console.ReadLine(); } // 带参数的方法参数必须是object类型 static void CalculateSum(object maxObj) { int max (int)maxObj; // 拆箱 int sum 0; for (int i 1; i max; i) sum i; Console.WriteLine($工作线程: 1到{max}的和是{sum}); }}输出示例工作线程: 1到10的和是55Lambda线程计算结果: 15注释说明-ParameterizedThreadStart允许传递一个object参数。但需要注意拆箱的类型安全。- Lambda表达式更简洁且可以捕获外部变量注意闭包陷阱是现代.NET多线程编程的首选方式。### 三、线程同步避免竞态条件当多个线程访问共享资源如全局变量、文件、数据库连接时必须同步以防止数据不一致。最常用的同步机制是lock语句。#### 3.1 无同步的竞态条件演示先看一个反面教材csharpusing System;using System.Threading;class Program{ static int counter 0; // 共享资源 static void Main() { // 创建两个线程同时增加counter Thread t1 new Thread(IncrementCounter); Thread t2 new Thread(IncrementCounter); t1.Start(); t2.Start(); // 等待两个线程完成 t1.Join(); t2.Join(); Console.WriteLine($最终结果: {counter} (期望: 200000)); Console.ReadLine(); } static void IncrementCounter() { for (int i 0; i 100000; i) { // 非原子操作读取、加1、写入 counter; } }}输出示例每次运行可能不同最终结果: 156823 (期望: 200000)原因分析counter不是原子操作它包含“读取-修改-写入”三步。当两个线程同时读取到相同值比如100各自加1后写入结果只增加了1而不是2。这就是竞态条件。#### 3.2 使用lock同步修复方法用lock对象保护临界区csharpusing System;using System.Threading;class Program{ static int counter 0; // 锁对象必须是引用类型且通常设为private static readonly private static readonly object lockObj new object(); static void Main() { Thread t1 new Thread(IncrementCounter); Thread t2 new Thread(IncrementCounter); t1.Start(); t2.Start(); t1.Join(); t2.Join(); Console.WriteLine($最终结果: {counter} (期望: 200000)); Console.ReadLine(); } static void IncrementCounter() { for (int i 0; i 100000; i) { // 进入锁只允许一个线程执行此代码块 lock (lockObj) { counter; } // 离开锁其他线程可以进入 } }}输出结果稳定最终结果: 200000 (期望: 200000)注释说明-lock (lockObj)确保同一时间只有一个线程能执行花括号内的代码。- 锁对象选择必须是所有相关线程都能访问的引用类型且不要用this、typeof或字符串字面量因为这些可能被其他代码意外锁定。- 性能影响锁会引入开销因此只保护必要的临界区。### 四、高级抽象Task与async/await从.NET 4.0开始System.Threading.Tasks.Task提供了更高级的并行编程模型。它基于线程池自动管理线程的创建和复用。配合async/awaitC# 5.0可以写出类似同步代码的异步程序。#### 4.1 Task基础使用csharpusing System;using System.Threading.Tasks;class Program{ static void Main() { // 创建并启动一个Task Task task1 Task.Run(() { for (int i 0; i 3; i) { Console.WriteLine($Task1 运行中... 迭代 {i1}); Task.Delay(300).Wait(); // 模拟异步等待 } }); // 创建返回值的Task Taskint task2 Task.Run(() { int sum 0; for (int i 1; i 100; i) sum i; return sum; }); // 等待所有任务完成 Task.WaitAll(task1, task2); // 获取task2的结果会阻塞直到完成 Console.WriteLine($Task2 结果: {task2.Result}); // 使用ContinueWith链式操作 Task.Run(() Hello) .ContinueWith(prev Console.WriteLine(prev.Result World)) .Wait(); Console.ReadLine(); }}输出示例Task1 运行中... 迭代 1Task1 运行中... 迭代 2Task1 运行中... 迭代 3Task2 结果: 5050Hello World注释说明-Task.Run在线程池上执行异步操作推荐用于CPU密集型任务。-Task.Delay非阻塞的异步等待相比Thread.Sleep不会占用线程。-Task.WaitAll阻塞当前线程直到所有任务完成。-ContinueWith在任务完成后执行后续操作类似回调。#### 4.2 async/await异步编程async/await让异步代码更易读特别适合I/O密集型操作如文件读写、网络请求csharpusing System;using System.Net.Http;using System.Threading.Tasks;class Program{ static async Task Main(string[] args) // Main也可以async { Console.WriteLine(开始下载...); string content await DownloadWebPageAsync(https://example.com); Console.WriteLine($下载完成内容长度: {content.Length} 字符); // 并发下载多个页面 Taskstring task1 DownloadWebPageAsync(https://httpbin.org/get); Taskstring task2 DownloadWebPageAsync(https://httpbin.org/ip); // 等待所有任务完成不阻塞UI线程 string[] results await Task.WhenAll(task1, task2); Console.WriteLine($第一个结果长度: {results[0].Length}); Console.WriteLine($第二个结果长度: {results[1].Length}); Console.ReadLine(); } static async Taskstring DownloadWebPageAsync(string url) { using (HttpClient client new HttpClient()) { // await 会释放当前线程但不会阻塞调用者 string response await client.GetStringAsync(url); return response; } }}输出示例开始下载...下载完成内容长度: 1256 字符第一个结果长度: 312第二个结果长度: 45注释说明-async标记方法await等待异步操作完成。- 在await执行时当前线程会返回线程池不占用资源操作完成后从线程池取回线程继续执行。-Task.WhenAll并发等待多个任务提高效率。- 注意Main方法也可以标记为async TaskC# 7.1但控制台应用仍需要ReadLine保持进程。### 五、总结多线程开发是.NET中提升性能和响应性的核心技能。从最基础的Thread类到线程同步的lock再到现代的Task和async/await我们经历了一条从底层到高层的演进路径1.Thread类提供最直接的控制但手动管理线程生命周期和同步容易出错。适合需要精细控制线程优先级的场景。2.lock同步解决竞态条件但过度使用会降低并发性能。应只保护最小的临界区。3.Task与async/await基于线程池自动管理线程复用async/await让异步代码逻辑清晰避免回调地狱。推荐用于大多数现代.NET应用。在实际开发中建议优先使用Task和async/await仅在需要低级别控制时使用Thread。同时牢记线程安全原则共享可变资源必须同步而不可变数据或线程本地存储则不需要。掌握这些基础你就能构建出高效、稳定的多线程应用。

相关新闻

如何在5分钟内体验AI情感识别?零配置启动的实时情绪分析系统

如何在5分钟内体验AI情感识别?零配置启动的实时情绪分析系统

如何在5分钟内体验AI情感识别?零配置启动的实时情绪分析系统 【免费下载链接】Emotion-recognition Real time emotion recognition 项目地址: https://gitcode.com/gh_mirrors/em/Emotion-recognition 你是否曾想过,让计算机读懂你的表情&#…

2026/7/26 21:59:30 阅读更多 →
游戏一般开帧,mmo等即时战斗的或者对流畅度有很高要求的可以开帧。 帧同步与状态同步的抉择。一般来说状态同步会比帧同步的前后端消息量 ...

游戏一般开帧,mmo等即时战斗的或者对流畅度有很高要求的可以开帧。 帧同步与状态同步的抉择。一般来说状态同步会比帧同步的前后端消息量 ...

游戏帧同步与状态同步的抉择:从开帧到消息量的深度解析 作为一名资深技术博主,今天我们来聊聊游戏开发中一个绕不开的话题——帧同步与状态同步的抉择。特别是对于MMO(大型多人在线)游戏、即时战斗类游戏或者对流畅度有很高要求的…

2026/7/26 21:59:30 阅读更多 →
基于OpenClaw与SeekDB构建智能知识库检索系统

基于OpenClaw与SeekDB构建智能知识库检索系统

1. 项目背景与核心价值 最近在整理个人知识库时,发现一个痛点:虽然用seekdb存储了大量技术笔记和参考资料,但随着数据量增长,检索效率越来越低。每次都要手动输入复杂查询条件,特别在跨多个标签搜索时尤为麻烦。于是萌…

2026/7/26 21:59:30 阅读更多 →

最新新闻

【AI图片细节放大终极指南】:20年图像算法专家亲授5大不可告人的超分辨率实战技巧

【AI图片细节放大终极指南】:20年图像算法专家亲授5大不可告人的超分辨率实战技巧

更多请点击: https://kaifayun.com 第一章:AI图片细节放大图的本质与挑战 AI图片细节放大图,即超分辨率(Super-Resolution, SR)重建,是指利用深度学习模型从低分辨率(LR)图像中恢复…

2026/7/26 22:21:42 阅读更多 →
如何快速上手SimpleRemote?5分钟搭建你的远程管理工作站

如何快速上手SimpleRemote?5分钟搭建你的远程管理工作站

如何快速上手SimpleRemote?5分钟搭建你的远程管理工作站 【免费下载链接】SimpleRemote Remote Administration Tools 项目地址: https://gitcode.com/gh_mirrors/si/SimpleRemote SimpleRemote是一款高效的远程管理工具,能够帮助用户轻松建立多种…

2026/7/26 22:21:42 阅读更多 →
Unity中Mixamo动画重定向至VRoid角色:从原理到流畅播放全流程

Unity中Mixamo动画重定向至VRoid角色:从原理到流畅播放全流程

1. 项目概述:为什么选择Mixamo驱动VRoid角色?如果你正在用Unity捣鼓一个二次元风格的游戏或者动画项目,手头有一个从VRoid Studio精心捏出来的可爱角色模型,那么接下来最头疼的问题大概率就是动画了。自己手K动画?门槛…

2026/7/26 22:21:42 阅读更多 →
MySQL数据截断异常解析与实战处理

MySQL数据截断异常解析与实战处理

1. MySQL数据截断异常解析与实战处理当你在Java应用中看到"com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Out of range value for column"这样的报错时,说明程序正在尝试向MySQL数据库插入或更新超出列定义范围的数据。这个异常看…

2026/7/26 22:21:42 阅读更多 →
LERF 代码结构解析:从 lerf.py 到图像编码器的核心模块

LERF 代码结构解析:从 lerf.py 到图像编码器的核心模块

LERF 代码结构解析:从 lerf.py 到图像编码器的核心模块 【免费下载链接】lerf Code for LERF: Language Embedded Radiance Fields 项目地址: https://gitcode.com/gh_mirrors/le/lerf LERF(Language Embedded Radiance Fields)是一个…

2026/7/26 22:21:42 阅读更多 →
JAVA面试题学习7 - SpingBean循环依赖如何解决

JAVA面试题学习7 - SpingBean循环依赖如何解决

问题SpingBean循环依赖如何解决解答产生原因当 Spring 容器加载时,会进行创建 Bean,令该 Bean 为 A,在 A 创建过程中,会进行实例化 -> 属性赋值(依赖注入,Autowired)-> 加入一级缓存&…

2026/7/26 22:20:41 阅读更多 →

日新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/26 0:00:31 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/26 0:00:31 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/26 0:00:31 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/26 0:00:31 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/26 0:00:31 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/26 0:00:31 阅读更多 →

月新闻