C# 多线程(3)——线程池

news/2024/4/21 13:34:18/文章来源:https://blog.csdn.net/contact97/article/details/135927997

文章目录

      • 1 定义
      • 2 线程池使用
      • 3 安全取消线程池中任务

1 定义

线程是计算机宝贵的资源,频繁的创建和销毁线程将会大量的占用计算机资源(为每个线程单独分配内存空间,并且多线程下的CPU时间片的切换也会耗费一定的时间)。为了充分利用硬件资源以及避免线程过多的创建和销毁,可用利用 线程池 \textcolor{red}{线程池} 线程池来管理工作线程。

使用者把任务(需要执行的代码)交给线程池,也就是加入线程池的 任务队列 \textcolor{red}{任务队列} 任务队列 ,工作线程完成之前的任务后,就继续从队列中取任务执行。如果没有工作线程空闲,而队列中还有任务,线程池就可能会创建新的工作线程来处理任务。而如果工作线程空闲太久,就会被销毁,并释放占用的资源。
.Net线程池是这个这个概念的实现,可以通过System.Threading.ThreadPool类来使用线程池。

一般的原则是:短时间的和少量并发的任务可以交给线程池,而长时间或大量并发的任务最好自己处理,来达到更好的效果。
如非必须,不要手动设置线程池的最小线程数和最大线程数,CLR会自动的进行线程池的扩张和收缩,手动干预往往让性能更差。
值得注意的是,线程池中的线程都是后台线程,当所有的前台线程全部结束时。后台线程也跟着结束。

2 线程池使用

//1 将异步方法加入到任务队列中。当线程池的工作线程可用时,使用工作线程去执行该异步方法
//2 异步方法成功加入到任务队列中时,返回true,超过任务队列长度时,将抛出System.NotSupportedException异常     
public static bool QueueUserWorkItem(WaitCallback callBack){}public delegate void WaitCallback(object state);

查看方法定义可知,ThreadPool中有一个静态类 Q u e u e U s e r W o r k I t e m \textcolor{red}{QueueUserWorkItem} QueueUserWorkItem ,调用该方法能将任务直接加入到线程池的任务队列中。任务的执行将交由线程池中的线程来执行。该方法接收一个类型为 W a i t C a l l b a c k \textcolor{red}{WaitCallback} WaitCallback委托参数,通常将需要执行的代码封装到这个委托方法中。还可以使用 l a m d a \textcolor{red}{lamda} lamda表达式的方式去传递异步方法。
在目标代码中需要显式地处理异常,否则未处理的异常会令程序结束 \textcolor{red}{在目标代码中需要显式地处理异常,否则未处理的异常会令程序结束} 在目标代码中需要显式地处理异常,否则未处理的异常会令程序结束

        static void Main(string[] args){//定义一个异步方法void AsyncOperation(Object state){Console.OutputEncoding = Encoding.UTF8;Console.WriteLine("OperationState {0}", state ?? "null");Console.WriteLine("当前工作线程id{0}", Thread.CurrentThread.ManagedThreadId);Thread.Sleep(TimeSpan.FromSeconds(2));}//Console.WriteLine("此计算机处理器数量:" + Environment.ProcessorCount);//ThreadPool是受CLR管理的//可以通过静态方法QueueUserWorkItem(WaitCallback callBack)向线程池中的工作队列放入工作//public delegate void WaitCallback(object state)//其中 state 是一个对象,其中包含委托要使用的数据。 可以通过调用 QueueUserWorkItem(WaitCallback, Object) 方法将实际数据传递给委托。ThreadPool.QueueUserWorkItem(AsyncOperation);ThreadPool.QueueUserWorkItem(AsyncOperation,"state_1");//使用lamda表达式,将异步方法加入到线程池中 。与ThreadPool.QueueUserWorkItem(AsyncOperation) 方法等价ThreadPool.QueueUserWorkItem(state =>{Console.OutputEncoding = Encoding.UTF8;Console.WriteLine("OperationState {0}", state ?? "null");Console.WriteLine("当前工作线程id{0}", Thread.CurrentThread.ManagedThreadId);Thread.Sleep(TimeSpan.FromSeconds(2));});ThreadPool.QueueUserWorkItem(state =>{Console.OutputEncoding = Encoding.UTF8;Console.WriteLine("OperationState {0}", state ?? "null");Console.WriteLine("当前工作线程id{0}", Thread.CurrentThread.ManagedThreadId);Thread.Sleep(TimeSpan.FromSeconds(2));},"lamda_state_1");Console.ReadKey();}

在这里插入图片描述

3 安全取消线程池中任务

当加入到线程池的工作任务由于编码错误,可能会导致线程被卡住,导致无限期的等待(超时请求);这种情况下需要一种机制去取消线程池的任务。线程池支持实现一个 协作( c o o p e r a t i v e ) \textcolor{red}{协作(cooperative )} 协作(cooperative模式,来安全地取消线程池中任务的执行。这里需要用到 C a n c e l l a t i o n T o k e n S o u r c e 、 C a n c e l l a t i o n T o k e n 类 \textcolor{red}{CancellationTokenSource、CancellationToken 类} CancellationTokenSourceCancellationToken。CancellationToken 是用于获得提前终止执行的型号。

 static void Main(string[] args){Console.OutputEncoding = Encoding.Unicode;void AsyncOperation1(CancellationToken token){Console.WriteLine("启动第一个任务. 时间为{0}",DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));for (int i = 0; i < 5; i++){//判断任务是否取消if (token.IsCancellationRequested){Console.WriteLine("取消第一个任务. 时间为{0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));return; //结束任务}Thread.Sleep(TimeSpan.FromSeconds(1));}Console.WriteLine("第一个任务运行完成.");}void AsyncOperation2(CancellationToken token) {try{Console.WriteLine("启动第二个任务. 时间为{0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));for (int i = 0; i < 5; i++){Thread.Sleep(TimeSpan.FromSeconds(1));//手动抛出异常ThrowIfCancellationRequested。只有在发出了取消请求时,异常才会被抛出token.ThrowIfCancellationRequested();}Console.WriteLine("第二个任务运行完成.");}catch (OperationCanceledException e) {//捕获OperationCanceledException异常,额外处理终止逻辑Console.WriteLine("捕获异常,取消第二个任务. 时间为{0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));}}using (var cts = new CancellationTokenSource()){CancellationToken token = cts.Token;ThreadPool.QueueUserWorkItem(_=>AsyncOperation1(token));Thread.Sleep(TimeSpan.FromSeconds(2));cts.Cancel(); //休眠2s后取消异步操作}using (var cts = new CancellationTokenSource()){CancellationToken token = cts.Token;ThreadPool.QueueUserWorkItem(_ => AsyncOperation2(token));Thread.Sleep(TimeSpan.FromSeconds(2));cts.Cancel(); //休眠2s后取消异步操作}Console.ReadKey();}

在这里插入图片描述

在上述代码中,有两种方式来实现任务的中断。
通过实现轮训检验CancellationToken 的IsCancellationRequested属性来判断是否需要加入到线程池中的工作任务。如果该属性为true时 ,则说明操作需要被取消。第二种方式是捕获一个OperationCanceledException 异常,允许在异常处理中去终止任务的运行。

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

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

相关文章

Supplementary Influence Maximization Problem in Social Networks

本论文发表于 IEEE TRANSACTIONS ON COMPUTATIONAL SOCIAL SYSTEMS, VOL. 11, NO. 1, FEBRUARY 2024 Abstract 由于在病毒式营销中的重要应用&#xff0c;影响力最大化&#xff08;IM&#xff09;已成为一个经过充分研究的问题。它的目的是找到一小部分初始用户&#xff0c;以…

基于Python3的数据结构与算法 - 12 数据结构(列表和栈)

目录 一、引入 二、分类 三、列表 1. C语言中数组的存储方式 2. Python中列表的存储方式 四、栈 1. 栈的应用 -- 括号匹配问题 一、引入 定义&#xff1a;数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。简单来说&#x…

异常-Exception

文章目录 异常-Exception常见的运行时异常NullPointerException&#xff08;空指针异常&#xff09;ArithmeticException&#xff08;数学运算异常&#xff09;ArrayIndexOutOfBoundsException&#xff08;数组下标越界异常&#xff09;ClassCastException&#xff08;类型转换…

浏览器修改接口返回数据展示在页面上

前端自己调试&#xff0c;想修改接口返回来的数据&#xff0c;然后展示在页面上 举例 接口返回了数据&#xff0c;想要修改此数据 这时就可以修改数据了&#xff0c;修改完成保存 然后刷新页面就会使用本地保存的数据了

Linux第68步_旧字符设备驱动的一般模板

file_operations结构体中的函数就是我们要实现的具体操作函数。 注意&#xff1a; register_chrdev()和 unregister_chrdev()这两个函数是老版本驱动使用的。现在新字符设备驱动已经不再使用这两个函数&#xff0c;而是使用Linux内核推荐的新字符设备驱动API函数。 1、创建C…

“TXT文本编辑专家:一键查找,多关键字,高效办公新选择“

办公场景中&#xff0c;我们经常需要处理大量的TXT文本文件&#xff0c;从中筛选出包含特定关键字的内容。传统的文本编辑软件往往功能单一&#xff0c;无法满足多关键字、多文件的同时查找需求。现在&#xff0c;一款专为TXT文本编辑设计的办公软件应运而生&#xff0c;它将为…

ArcGIS学习(十一)公服设施服务区划分与评价

ArcGIS学习(十一)公服设施服务区划分与评价 本任务带来的内容是公服设施服务区划分与公服设施服务区评价。本任务包括两个关卡: 公服设施服务区划分公服设施服务区空间价值评价1.公服设施服务区划分 首先,来看看这个案例的场景和基础数据。我们以上海市图书馆为例进行分析…

使用docker安装运行rabbitmq---阿里云服务器

目录 0、阿里云没开端口的得要去安全组规则去添加&#xff1a; 1、下载RabbitMQ镜像&#xff1a; 2、查看镜像是否下载成功&#xff0c;得到docker镜像id&#xff1a; 3、运行RabbitMQ: 4、查看RabbbitMQ容器是否启动成功&#xff1a; 5、启动RabbitMQ中的插件管理 6、访…

微信小程序 ---- 慕尚花坊 用户管理

01. 用户登录-什么是 token 什么是 Token Token 是服务器生成的一串字符串&#xff0c;用作客户端发起请求的一个身份令牌。当第一次登录成功后&#xff0c;服务器生成一个 Token 便将此 Token 返回给客户端&#xff0c;客户端在接收到 Token 以后&#xff0c;会使用某种方式…

.NetCore6.0实现ActionFilter过滤器记录接口请求日志

文章目录 目的实现案例&#xff1a;一.首先我们新建一个WebApi项目二.配置 appsettings.json 文件&#xff0c;配置日志存放路径三.创建 Model 文件夹&#xff0c;创建AppConfig类和ErrorLog类1.在AppConfig类中编写一个GetConfigInfo方法获取配置文件中的值2.在ErrorLog类中&a…

大数据组件之图数据库JanusGraph图文介绍

前言 大数据时代&#xff0c;面对复杂关联数据的存储与检索需求&#xff0c;图数据库以其强大的关联数据处理能力和直观的图形模型展示&#xff0c;已成为大数据处理领域的一项关键技术。JanusGraph作为一款专门为满足超大规模图数据处理而设计的分布式图数据库系统&#xff0…

STM32 NAND FLASH知识点

1.NAND FLASH的简介 NAND FLASH 的概念是由东芝公司在 1989 年率先提出&#xff0c;它内部采用非线性宏单元模式&#xff0c;为固态大容量内存的实现提供了廉价有效的解决方案。 NAND FLASH 存储器具有容量较大&#xff0c;改写速度快等优点&#xff0c;适用于大量数据的存储&…

SpringBoot整合Redis实现分布式锁

SpringBoot整合Redis实现分布式锁 分布式系统为什么要使用分布式锁&#xff1f; 首先&#xff0c;分布式系统是由多个独立节点组成的&#xff0c;这些节点可能运行在不同的物理或虚拟机器上&#xff0c;它们通过网络进行通信和协作。在这样的环境中&#xff0c;多个节点可能同…

Vue事件处理:.passive修饰符与应用场景

.passive修饰符 passive这个修饰符会执行默认方法。你们可能会问&#xff0c;明明默认执行为什么会设置这样一个修饰符。这就要说一下这个修饰符的本意了。 浏览器只有等内核线程执行到事件监听器对应的JavaScript代码时&#xff0c;才能知道内部是否会调用preventDefa…

如何在Windows环境下编译OpenOCD

1. 安装Cygwin Windows环境下编译OpenOCD可以是在MinGW-w64/MSYS或Cygwin下&#xff0c;这里选择Cygwin&#xff0c;下载安装Cygwin。 2. 进入OpenOCD源代码目录 打开Cygwin&#xff0c;进入OpenOCD源代码目录&#xff0c;例如代码放在D:\Temp\OpenOCD\openocd-code下&#…

不注册访问 Claude3 大模型

随着Claude3大模型的出世&#xff0c;大模型霸主地位已经发生易位&#xff0c;但是国内使用Claude3官网 无论是注册都不容易&#xff0c;本篇文章主要介绍如何不通过Claude3 官网实现Claude3 大模型的使用&#xff0c;这里优先推荐Chatbot Arena 一、直接通过第三方代理 Chatb…

JsonCreator注解InvalidDefinitionException报错解决

"stack_trace": "c.f.j.d.e.InvalidDefinitionException: More than one argument (#0 and left as delegating for Creator [constructor for (

Django 创建第一个项目

Django 创建第一个项目 本章我们将介绍 Django 管理工具及如何使用 Django 来创建项目&#xff0c;第一个项目我们以 HelloWorld 来命令项目。 测试版本说明&#xff1a; Python 3.9.7 Django 4.2.7 通过以下命令可以查看版本号&#xff1a; # python3 -V Python 3.9.7 #…

Material UI 5 学习02-其它按钮组件

Material UI 5 学习02-其它按钮组件 一、IconButton按钮二、 ButtonGroup按钮组1、最基本的实例2、垂直按钮组 一、IconButton按钮 图标按钮通常适用于切换按钮&#xff0c;允许选择或选择单个选项 取消选择&#xff0c;例如在项目中添加或删除星号。 <IconButton aria-lab…

Linux网络编程 ——TCP套接字通信

Linux网络编程——TCP套接字通信 7. TCP 三次握手8. TCP 滑动窗口9. TCP 四次挥手10. TCP 通信并发11. TCP 状态转换12 端口复用 7. TCP 三次握手 TCP 是一种 面向连接的 单播协议&#xff0c;在发送数据前&#xff0c;通信双方必须在彼此间建立一条连接。所谓的“ 连接”&…