C#多线程编程详细教学

在C#中,多线程编程是一种非常重要的技术,它允许程序同时执行多个任务,从而提高了应用程序的响应性和整体性能。本文将详细介绍C#中的多线程编程,包括基本概念、线程创建、线程同步以及相关的代码示例。

一、基本概念

线程是操作系统进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

在C#中,可以通过多种方式创建和管理线程,包括使用Thread类、Task类以及Parallel类等。

二、使用Thread类创建线程

Thread类是C#中用于创建和控制线程的基本类。下面是一个简单的示例,展示了如何使用Thread类创建并启动一个新的线程:

using System;
using System.Threading;class Program
{static void Main(){Thread newThread = new Thread(DoWork);newThread.Start(); // 启动线程// 主线程继续执行其他任务Console.WriteLine("Main thread continues to do work...");newThread.Join(); // 等待新线程完成Console.WriteLine("New thread has finished its work.");}static void DoWork(){Console.WriteLine("New thread is doing work...");Thread.Sleep(2000); // 模拟耗时操作Console.WriteLine("New thread work completed.");}
}

在上面的示例中,DoWork方法包含新线程要执行的代码。通过创建Thread类的实例并传递DoWork方法作为参数,我们创建了一个新的线程。调用Start方法将启动新线程,而Join方法则用于在主线程中等待新线程完成。

三、使用Task类创建线程

从.NET Framework 4.0开始,引入了基于任务的异步模式(TAP),它提供了更高级别的抽象来简化异步编程。Task类是TAP的核心组件,它代表一个异步操作。下面是一个使用Task类的示例:

using System;
using System.Threading.Tasks;class Program
{static async Task Main(string[] args){Console.WriteLine("Starting a task...");Task task = Task.Run(() => DoWork()); // 在后台线程上运行DoWork方法// 等待任务完成或超时if (await Task.WhenAny(task, Task.Delay(3000)) == task){Console.WriteLine("Task completed successfully.");}else{Console.WriteLine("Task timed out.");}}static void DoWork(){Console.WriteLine("Task is doing work...");Task.Delay(2000).Wait(); // 模拟耗时操作Console.WriteLine("Task work completed.");}
}

在上面的示例中,我们使用Task.Run方法来在后台线程上执行DoWork方法。Task.WhenAny方法用于等待任务完成或超时。注意,在C# 7.1及更高版本中,Main方法可以被声明为async,这使得我们可以方便地在主线程中使用await关键字来等待异步操作。

四、线程同步

当多个线程访问共享资源时,可能会出现数据不一致或线程冲突的问题。为了确保线程安全,需要使用线程同步机制来协调线程之间的访问。C#提供了多种线程同步原语,如锁(lock)、Monitor、Mutex、Semaphore、SemaphoreSlim、Event、AutoResetEvent、ManualResetEvent、ManualResetEventSlim、Barrier、CountdownEvent、ReaderWriterLock和ReaderWriterLockSlim等。下面是一个使用lock关键字进行线程同步的简单示例:

using System;
using System.Threading;class Program
{static object lockObject = new object();static int sharedCounter = 0;static void Main(){Thread thread1 = new Thread(IncrementCounter);Thread thread2 = new Thread(IncrementCounter);thread1.Start();thread2.Start();thread1.Join();thread2.Join();Console.WriteLine("Final counter value: " + sharedCounter); // 期望输出为2,但由于没有同步,实际输出可能不是2}static void IncrementCounter(){lock (lockObject) // 使用lock进行同步{for (int i = 0; i < 100000; i++){sharedCounter++;}}}
}

在上面的示例中,我们使用lock关键字来确保在增加sharedCounter时只有一个线程能够访问它。通过将lock语句包围在要保护的代码块周围,我们确保了在任何时候只有一个线程能够执行该代码块。

需要注意的是,过度使用线程同步可能会导致性能下降,因此应该谨慎使用,并只在必要时进行同步。

五、线程安全

在C#中解决线程安全问题,可以采取以下几种策略:lock 关键字:使用lock关键字可以确保在给定时刻只有一个线程可以执行某段代码。这类似于Java中的synchronized代码块。

private readonly object lockObject = new object();public void MyThreadSafeMethod()
{lock (lockObject){// 线程安全的代码区域}
}

在上面的例子中,lockObject是一个私有的对象,用作同步锁。所有需要线程安全的代码都应该放在lock语句块内。Monitor 类:Monitor类提供了与lock关键字相同的功能,但它是通过方法调用的形式来实现的。它提供了更细粒度的控制,但通常lock关键字更简洁且易于使用。

private readonly object monitorObject = new object();public void MyThreadSafeMethod()
{Monitor.Enter(monitorObject);try{// 线程安全的代码区域}finally{Monitor.Exit(monitorObject);}
}

使用Monitor类时,必须确保在finally块中调用Monitor.Exit来释放锁,以避免死锁。Mutex 类:Mutex(互斥体)是操作系统级别的同步原语,用于跨进程同步。如果你需要在不同的进程间同步访问资源,可以使用Mutex。


Mutex mutex = new Mutex(false, "MyMutexName");public void MyThreadSafeMethod()
{mutex.WaitOne();try{// 线程安全的代码区域}finally{mutex.ReleaseMutex();}
}

ReaderWriterLockSlim 类:对于读多写少的场景,ReaderWriterLockSlim是一个很好的选择。它允许多个线程同时读取共享资源,但在写入时只允许一个线程访问。
 

private readonly ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();public void ReadData()
{rwLock.EnterReadLock();try{// 读取共享数据的代码}finally{rwLock.ExitReadLock();}
}public void WriteData()
{rwLock.EnterWriteLock();try{// 写入共享数据的代码}finally{rwLock.ExitWriteLock();}
}

使用线程安全的集合:C# 提供了许多线程安全的集合类,如ConcurrentDictionary<TKey, TValue>、ConcurrentQueue<T>、ConcurrentBag<T>等。这些集合内部实现了必要的同步机制,使得在多线程环境下可以安全地使用。

避免共享状态:尽量减少线程间的数据共享,使用局部变量或不可变对象来避免潜在的线程安全问题。

异步编程:利用C#中的异步编程模型(如async和await关键字),可以更有效地管理线程,减少线程间的竞态条件。异步编程使得线程在等待I/O操作(如文件读写、网络请求)时不会被阻塞,从而提高了应用程序的响应性和吞吐量。

在选择解决线程安全问题的策略时,需要根据具体的应用场景和需求来权衡。有时候,简单的lock或Monitor就能满足需求,而在复杂的场景下,可能需要结合多种策略来确保线程安全。

六、总结

C#提供了强大的多线程编程支持,通过Thread、Task等类可以方便地创建和管理线程。然而,多线程编程也带来了线程安全和同步的问题,需要使用适当的同步机制来确保数据的一致性和避免线程冲突。在编写多线程程序时,应该仔细考虑线程间的交互和共享资源的访问方式,以确保程序的正确性和性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/787059.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【新手适用】手把手教你从零开始实现一个基于Pytorch的卷积神经网络CNN二: 如何训练模型,内附详细损失、准确率、均值计算

手把手教你从零开始实现一个基于Pytorch的卷积神经网络CNN&#xff08;新手适用&#xff09;一&#xff1a; model.py&#xff1a;创建模块-CSDN博客 从零开始实现一个基于Pytorch的卷积神经网络 - 知乎 目录 1 设备device定义 2 训练模型定义 3 开始训练 3.1 step、batch…

4.机器学习-十大算法之一线性回归算法(LinearRegression)案例讲解

机器学习-十大算法之一线性回归算法案例讲解 一摘要二个人简介三什么是线性回归四LinearRegression使用方法五糖尿病数据线性回归预测1.数据说明2.导包3.导入数据4.脱敏处理5.抽取训练数据和预测数据6.创建模型7.预测8.线性回归评估指标9.研究每个特征和标记结果之间的关系.来分…

职场成功的关键:提升软实力,成就非凡事业

在竞争激烈的职场中&#xff0c;专业技能固然重要&#xff0c;但软实力同样不可或缺。要想在职场中脱颖而出&#xff0c;实现事业上的成功&#xff0c;我们需要在提升软实力上下功夫。本文将探讨职场软实力的内涵及其在职场成功中的作用&#xff0c;并提供一些建议&#xff0c;…

解决Quartus与modelsim联合仿真问题:# Error loading design解决,是tb文件中没加:`timescale 1ns/1ns

解决Quartus与modelsim联合仿真问题&#xff1a;# Error loading design解决&#xff0c;是tb文件中没加&#xff1a;timescale 1&#xff0c;一直走下来&#xff0c;在modelsim中出现了下面问题2&#xff0c;rtl文件、tb文件2.1&#xff0c;rtl代码2.2&#xff0c;tb测试2.3&a…

java Web实现用户登录功能

文章目录 一、纯JSP方式实现用户登录功能&#xff08;一&#xff09;实现思路1、创建Web项目2、创建登录页面3、创建登录处理页面4、创建登录成功页面5、创建登录失败页面6、编辑项目首页 &#xff08;三&#xff09;测试结果 二、JSPServlet方式实现用户登录功能&#xff08;一…

校园通勤车可视化系统的设计与实现

1.需求分析&#xff1a; 校园通勤车可视化系统的设计与实现&#xff0c;不用管什么可视化&#xff0c;就是一个小程序就是可以知道校园车的路线&#xff0c;然后往简单了弄就可以。 校园通勤车可视化系统的设计与实现&#xff0c;不用管什么可视化&#xff0c;就是一个小程序…

【C/C++】C++学籍信息管理系统(源码+报告)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

【threejs】较大物体或shape的贴图较小问题处理方法

问题 有的场景内相对体型差距过大的物体&#xff08;如山地 海洋等&#xff09;由于尺寸问题&#xff0c;加载贴图过于小&#xff0c;同时shader也无法完全展示&#xff0c;如图 我们可以获取物体的uv&#xff0c;进行缩放使得贴图可以完全展开 如果uv是乱的 可以用xyz坐标最…

【Redis】MISCONF Redis is configured to save RDB snapshots报错解决方案

【Redis】MISCONF Redis is configured to save RDB snapshots报错解决方案 大家好 我是寸铁&#x1f44a; 总结了一篇【Redis】MISCONF Redis is configured to save RDB snapshots报错解决方案✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 前言 今天在登录redis时&#xff0c…

matlab函数化简和函数极限

文章目录 化简求函数极限泰勒公式泰勒公式求解 化简 simplify 函数是MATLAB中符号计算工具箱提供的一个函数&#xff0c;用于简化数学表达式。它可以根据预定义的简化规则&#xff0c;对给定的数学表达式进行简化和转化。 以下是simplify 函数的一些常用用法&#xff1a; 简…

[蓝桥杯 2022 省 B] 李白打酒加强版

题目链接 [蓝桥杯 2022 省 B] 李白打酒加强版 题目描述 话说大诗人李白&#xff0c;一生好饮。幸好他从不开车。 一天&#xff0c;他提着酒壶&#xff0c;从家里出来&#xff0c;酒壶中有酒 2 2 2 斗。他边走边唱&#xff1a; 无事街上走&#xff0c;提壶去打酒。 逢店加一倍…

python_绘图_多条折线图绘制_显示与隐藏

1. 需求 给定一个二维数组 100行, 5列, 每一列绘制一条折线, 横轴为行索引, 纵轴为对应位置的值, 绘制在一个子图里面, 使用python plot, 使用随机颜色进行区别添加显示和隐藏按钮, 可以对每条折线进行显示和隐藏 2. 代码 import numpy as np import matplotlib.pyplot as p…

为什么说FMEA是最主要的可靠性设计工具?——FMEA软件

免费试用FMEA软件-免费版-SunFMEA FMEA&#xff0c;即故障模式与影响分析&#xff08;Failure Modes and Effects Analysis&#xff09;&#xff0c;是一种预防性的质量工具&#xff0c;广泛应用于各种工程领域&#xff0c;特别是在产品设计和制造过程中。它通过对产品或过程中…

工具_git提交时忽略某些文件或者目录,git提交排除某些文件或目录

git 提交时如果想忽略某些文件或者目录&#xff1a; 1.在根目录下创建 .gitignore 文件 2.在该文件中直接添加内容&#xff0c;如&#xff1a; 忽略.mdb、.sln、.sln,.config 文件&#xff0c;不忽视 .txt 文件 *.mdb *.ldb *.sln .config !.txt 忽略Debug目录及文件&#…

4月2日 qt密码生成小程序(可选择生成密码的格式),基于Python框架下的pyqt6

4月2日 密码生成小程序 代码展示&#xff1a; import stringfrom PyQt6.QtWidgets import (QApplication, QDialog,QMessageBox ) from untitled import Ui_PasswordGender import sys import string # py模块含有字符 import randomclass MyPasswordGenerate(Ui_Password…

快速入门Linux,Linux岗位有哪些?(一)

文章目录 Linux与Linux运维操作系统&#xff1f;操作系统图解 认识LinuxLinux受欢迎的原因什么是Linux运维Linux运维岗位Linux运维岗位职责Linux运维架构师岗位职责Linux运维职业发展路线计算机硬件分类运维人员的三大核心职责 运维人员工作&#xff08;服务器&#xff09;什么…

python爬虫----了解爬虫(十一天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

6000000IOPS!FASS×kunpeng920全新突破

实测数据详见下文 网络环境 前端和后端网均采用100GE网络&#xff0c;管理网采用1Gbps以太网。 前端网和后端网通过不同网段隔离&#xff0c;与管理网物理隔离。 软硬件配置 存储端配置&#xff1a; 客户端配置&#xff1a; 软件配置&#xff1a; 存储集群配置&#xff1a; …

【MapBox】实现实时飞行轨迹功能

之前写了一篇MapBox添加带箭头的轨迹线&#xff0c;现在在这个基础之上实现获取到无人机的推送点位数据实时飞行的功能 首先创建实例&#xff0c;将无人机的图标加载在地图上 const MAP_UAV_FLIGHT_ING (values, layerKey 无人机飞行) > {ClearUAVMap();const map GET_…

认证的无线网络安全

​在今天&#xff0c;大多数计算机网络都是无线网络&#xff0c;更易管理&#xff0c;移动性更强&#xff0c;而且成本也更低。而另一方面&#xff0c;无线网络也更容易受到攻击&#xff0c;因为企业无法将网络的物理范围控制在办公楼内&#xff0c;大街或停车场上的任何人都有…