C# 多线程
文章目录
- C# 多线程
- 进程与线程
- 无参数的子线程
- 带参数的子线程
- 运行结果
- 销毁线程 Abort()
- 运行结果
- ThreadPool和Task
- 运行结果
- 异步与同步
- 运行结果
- lock
- 单线程
- 运行结果
- 多线程
- 运行结果
- 使用lock
- 运行结果
C# 多线程
进程与线程
进程:进程就是一个应用程序,对电脑的各种资源的占用
线程:线程是程序执行的最小单位,任何操作都是线程完成的,线程依托进程存在的,一个进程可以有多个线程
无参数的子线程
public static void ChildThread1(){Console.WriteLine("Child thread1 is starts");}
带参数的子线程
ChildThread2
是带参数的子线程,所以要使用ParameterizedThreadStart
类型的委托来指定子线程
如果使用的是不带参数的委托,不能使用带参数的Start方法运行线程,否则系统会抛出异常。
但使用带参数的委托,可以使用thread.Start()来运行线程,这时所传递的参数值为null。
特别注意:ParameterizedThreadStart委托的参数类型必须是object的
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{public static void ChildThread1(){Console.WriteLine("Child thread1 is starts");}//注意:ParameterizedThreadStart委托的参数类型必须是object的public static void ChildThread2(object obj){Console.WriteLine("Child thread2 is starts,the parameter is {0}", obj);}public static void Main(){ThreadStart thread1 = new ThreadStart(ChildThread1); //通过ThreadStart委托指定子线程的方法ParameterizedThreadStart thread2 = new ParameterizedThreadStart(ChildThread2); //有参的委托Console.WriteLine("MainThread:Creating the child thread1");Console.WriteLine("MainThread:Creating the child thread2");Thread childThread1 = new Thread(thread1); //创建子线程1Thread childThread2 = new Thread(thread2);//创建子线程2childThread1.Start(); //运行子线程1childThread2.Start("子线程2的参数");//运行子线程2,传递参数,//如果使用的是不带参数的委托,不能使用带参数的Start方法运行线程,否则系统会抛出异常。//但使用带参数的委托,可以使用thread.Start()来运行线程,这时所传递的参数值为null。Console.ReadKey();}}
}
运行结果
销毁线程 Abort()
使用Abort()
中止子线程.
通过抛出 threadabortexception
在运行时中止线程。这个异常不能被捕获,如果有 finally 块,控制会被送至 finally 块。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{public static void ChildThread1(){Console.WriteLine("Child thread1 is starts");}//注意:ParameterizedThreadStart委托的参数类型必须是object的public static void ChildThread2(object obj){Console.WriteLine("Child thread2 is starts,the parameter is {0}", obj);}public static void ChildThread3(){try{Console.WriteLine("Child thread3 starts");for (int i = 0; i < 5; i++){Thread.Sleep(100);Console.WriteLine(i);}Console.WriteLine("Child Thread3 Completed");}catch (ThreadAbortException e){Console.WriteLine("Thread Abort Exception");}finally{Console.WriteLine("Couldn't catch the thread Exception");}}public static void Main(){ThreadStart thread3 = new ThreadStart(ChildThread3);Console.WriteLine("MainThread:Creating the child thread3");Thread thread = new Thread(thread3);thread.Start();//停止主线程1000Thread.Sleep(2000);Console.WriteLine("In Main: Aborting the Child thread");thread.Abort();Console.ReadKey();}}
}
运行结果
ThreadPool和Task
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{public static Thread t = null;public static void ChildThread1(){int i = 5;while (i > 0){Console.WriteLine(string.Format("线程【1】的i:{0} ", i));Thread.Sleep(10);i--;}Console.WriteLine("线程【1】结束");//Console.WriteLine("Child thread1 is starts");}//注意:ParameterizedThreadStart委托的参数类型必须是object的public static void ChildThread2(object obj){int i = 5;while (i > 0){Console.WriteLine(string.Format("线程【2】的i:{0} ", i));Thread.Sleep(10);i--;}Console.WriteLine("线程【2】结束");}public static void ChildThread3(){int i = 5;while (i > 0){Console.WriteLine(string.Format("线程【3】的i:{0} ", i));Thread.Sleep(10);i--;}Console.WriteLine("线程【3】结束");}public static void Main(string[] args){t = new Thread(new ThreadStart(ChildThread1));t.Start();//用线程池ThreadPool.QueueUserWorkItem(ChildThread2, new object());//用Task方法创建System.Threading.Tasks.Task.Factory.StartNew(ChildThread3);Console.ReadLine();}}
}
运行结果
线程都是独立的,不会互相影响。
异步与同步
C# 5.0引入了异步方法(Async Methods)的概念,使得编写异步代码变得更加容易。异步方法使用async关键字标记,返回类型必须是Task或Task,方法中使用await关键字来等待异步操作完成。通过使用异步方法,可以在不阻塞主线程的情况下执行耗时操作,从而提高程序的并发性和响应性。示例如下:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{public static async Task Main(string[] args){await DownloadWebsiteAsync();Console.ReadKey();}static async Task DownloadWebsiteAsync(){using (HttpClient client = new HttpClient()){string website = "https://www.example.com";string content = await client.GetStringAsync(website);Console.WriteLine("等待异步执行完成");}}}
}
运行结果
lock
如果你想控制多线程的线程的执行顺序,就需要用到lock
参考链接:https://blog.csdn.net/u012563853/article/details/124767902
单线程
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{static int a = 0;static int b = 0;private static object o = new object();static void Main(string[] args){methodA();methodB();Console.ReadKey();}private static void methodA(){Console.WriteLine("我是A方法");}private static void methodB(){Console.WriteLine("我是B方法");}private static void methodC(){Console.WriteLine("我是C方法,是随机出现的");}}
}
这样是按顺序执行的,因为是单线程的,先执行methodA,再去执行methodB
运行结果
多线程
我们增加了多线程,就是让A和B方法同时执行,此时,结果就是不可控制的。有时候先执行B方法,有时候先执行A方法。先执行B方法。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{static int a = 0;static int b = 0;private static object o = new object();static void Main(string[] args){//methodA();//methodB();Thread t1 = new Thread(methodA);Thread t2 = new Thread(methodB);t1.Start();t2.Start();Console.ReadKey();}private static void methodA(){a = 1;Console.WriteLine("我是A方法,a=" + a);Thread.Sleep(2000); //暂停5秒b = 2;Console.WriteLine("我是A方法,b=" + b);}private static void methodB(){a++;Console.WriteLine("我是B方法,a=" + a);Thread.Sleep(1000); //暂停1秒b++;Console.WriteLine("我是B方法,b=" + b);}private static void methodC(){Console.WriteLine("我是C方法,是随机出现的");}}
}
运行结果
所以,我们可以使用lock去锁住代码段,锁住的这段代码,此时只能有一个线程去访问,只有等这个线程访问结束了,其他线程才能访问。
使用lock
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApp2
{class Test{static int a = 0;static int b = 0;private static object o = new object();static void Main(string[] args){//methodA();//methodB();Thread t1 = new Thread(methodA);Thread t2 = new Thread(methodB);t1.Start();t2.Start();Console.ReadKey();}private static void methodA(){lock (o){a = 1;Console.WriteLine("我是A方法,a=" + a);Thread.Sleep(2000); //暂停5秒b = 2;Console.WriteLine("我是A方法,b=" + b);}}private static void methodB(){lock (o){a++;Console.WriteLine("我是B方法,a=" + a);Thread.Sleep(1000); //暂停1秒b++;Console.WriteLine("我是B方法,b=" + b);}}private static void methodC(){Console.WriteLine("我是C方法,是随机出现的");}}
}
运行结果
这样也是等效的:
Enter相当于进入这个代码块,Exit是退出这个代码块。当这个代码块再运行的时候,其他线程就不能访问。Monitor中的{}可以去掉,不影响。
相关文章:

C# 多线程
文章目录 C# 多线程进程与线程无参数的子线程带参数的子线程运行结果 销毁线程 Abort()运行结果 ThreadPool和Task运行结果 异步与同步运行结果 lock单线程运行结果 多线程运行结果 使用lock运行结果 C# 多线程 进程与线程 进程:进程就是一个应用程序,…...
快速安装sudachipy日语包
1、前往 https://rustup.rs 下载并安装 Rustup Linux系统可直接运行以下命令 Window系统需要去网站下载exe包 curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh2、安装 Rust 编译器 rustup install stable3、设置默认版本 rustup default stable4、重新安装 …...

蓝桥杯刷题day13——乘飞机【算法赛】
一、问题描述 等待登机的你看着眼前有老有小长长的队伍十分无聊,你突然想要知道,是否存在两个年龄相仿的乘客。每个乘客的年龄用一个 0 到 36500 的整数表示,两个乘客的年龄相差 365 以内就认为是相仿的。 具体来说,你有一个长度…...

大模型量化技术-BitsAndBytes
Transformers 量化技术 BitsAndBytes bitsandbytes是将模型量化为8位和4位的最简单选择。 8位量化将fp16中的异常值与int8中的非异常值相乘,将非异常值转换回fp16,然后将它们相加以返回fp16中的权重。这减少了异常值对模型性能产生的降级效果。4位量化进一步压缩了模型,并且…...

EasyExcel 复杂表头的导出(动态表头和静态表头)
问题:如图,1部分的表头是动态的根据日期变化,2部分是数据库对应的字段,静态不变的; 解决方案:如果不看1的部分,2部分内容可以根据实体类注解的方式导出,那么我们是不是可以先将动态表…...

centos7 fatal error: curl/curl.h: No such file or directory
若编译遇到此问题,可以查看环境是否libcurl库 yum list installed | grep libcurl 发现未安装libcurl库 执行libcurl库的安装命令: 1.对于Debian/Ubuntu系统: sudo apt-get install libcurl4-openssl-dev 2.对于RHEL/CentOS系统…...

【Linux】自定义协议+序列化+反序列化
自定义协议序列化反序列化 1.再谈 "协议"2.Cal TCP服务端2.Cal TCP客户端4.Json 喜欢的点赞,收藏,关注一下把! 1.再谈 “协议” 协议是一种 “约定”。在前面我们说过父亲和儿子约定打电话的例子,不过这是感性的认识&a…...
常见故障排查和优化
一、MySQL单实例故障排查 故障现象 1 ERROR 2002 (HY000): Cant connect to local MySQL server through socket /data/mysql/mysql.sock (2) 问题分析:以上情况一般都是数据库未启动或者数据库端口被防火墙拦截导致。 解决方法:启动数据库或者防火墙…...

选择华为HCIE培训机构有哪些注意事项
选择软件培训机构注意四点事项1、口碑:学员和社会人士对该机构的评价怎样? 口碑对于一个机构是十分重要的,这也是考量一个机构好不好的重要标准,包括社会评价和学员的评价和感言。誉天作为华为首批授权培训中心,一直致…...

python怎么处理txt
导入文件处理模块 import os 检测路径是否存在,存在则返回True,不存在则返回False os.path.exists("demo.txt") 如果你要创建一个文件并要写入内容 #如果demo.txt文件存在则会覆盖,并且demo.txt文件里面的内容被清空,如…...

SAMRTFORMS 转换PDF 发送邮件
最终成果: *&---------------------------------------------------------------------**& Report ZLC_FIND_EXIT*&---------------------------------------------------------------------**&根据T-CODE / 程序名查询出口、BADI增强*&-------…...

探讨在大数据体系中API的通信机制与工作原理
** 引言 关联阅读博客文章:深入解析大数据体系中的ETL工作原理及常见组件 关联阅读博客文章:深入理解HDFS工作原理:大数据存储和容错性机制解析 ** 在当今数字化时代,数据已经成为企业发展和决策的核心。随着数据规模的不断增长…...

算法打卡day23
今日任务: 1)39. 组合总和 2)40.组合总和II 3)131.分割回文串 39. 组合总和 题目链接:39. 组合总和 - 力扣(LeetCode) 给定一个无重复元素的数组 candidates 和一个目标数 target ,…...

每天五分钟深度学习:神经网络和深度学习有什么样的关系?
本文重点 神经网络是一种模拟人脑神经元连接方式的计算模型,通过大量神经元之间的连接和权重调整,实现对输入数据的处理和分析。而深度学习则是神经网络的一种特殊形式,它通过构建深层次的神经网络结构,实现对复杂数据的深度学习…...

基于PSO优化的CNN-LSTM-Attention的时间序列回归预测matlab仿真
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1卷积神经网络(CNN)在时间序列中的应用 4.2 长短时记忆网络(LSTM)处理序列依赖关系 4.3 注意力机制(Attention) 5…...

物联网监控可视化是什么?部署物联网监控可视化大屏有什么作用?
随着物联网技术的深入应用,物联网监控可视化成为了企业数字化转型的关键环节。物联网监控可视化大屏作为物联网监控平台的重要组成部分,能够实时展示物联网设备的运行状态和数据,为企业管理决策和运维监控提供了有力的支持。今天,…...
设计一个Rust线程安全栈结构 Stack<T>
在Rust中,设计一个线程安全的栈结构Stack<T>,类似于Channel<T>,但使用栈的FILO(First-In-Last-Out)原则来在线程间传送数据,可以通过使用标准库中的同步原语如Mutex和Condvar来实现。下面是一个…...

Docker Desktop 在 Windows 上的安装和使用
目录 1、安装 Docker Desktop 2、使用 Docker Desktop (1)运行容器 (2)查看容器信息 (3)数据挂载 Docker Desktop是Docker的官方桌面版,专为Mac和Windows用户设计,提供了一个简…...

2024年最受欢迎的 19 个 VS Code 主题排行榜
博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通鸿蒙》 …...
突破编程_C++_网络编程(OSI 七层模型(物理层与数据链路层))
1 OSI 七层模型概述 OSI(Open Systems Interconnection)七层模型,即开放系统互联参考模型,起源于 20 世纪 70 年代和 80 年代。随着计算机网络技术的快速发展和普及,不同厂商生产的计算机和网络设备之间的互操作性成为…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...

iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...