C#学习系列相关之多线程(五)----线程池ThreadPool用法
一、线程池的作用
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间之后创建另一个辅助线程。但线程的数目永远不会超过最大值。超过最大值的其他线程可以排队,但它们要等到其他线程完成后才启动。
线程池的使用范围:
(1)不需要前台执行的线程。
(2)不需要在使用线程具有特定的优先级。
(3)线程的执行时间不易过长,否则会使线程阻塞。由于线程池具有最大线程数限制,因此大量阻塞的线程池线程可能会阻止任务启动。
(4)不需要将线程放入单线程单元。所有 ThreadPool 线程均不处于多线程单元中。
(5)不需要具有与线程关联的稳定标识,或使某一线程专用于某一任务。
二、常用方法介绍
1.ThreadPool.QueueUserWorkItem
该方法是线程池中最主要的方法,ThreadPool.QueueUserWorkItem 方法是用于将工作项提交到线程池队列中的方法。当你需要执行一个方法但不想创建一个新的线程时,可以使用该方法。这个方法会将工作项放到一个线程池队列中,并由线程池中的一个线程来执行该工作项。
ThreadPool.QueueUserWorkItem(WaitCallback(DoWork), object)
该方法主要是两个参数,第一个是WaitCallback,第二个是一个object,object参数可以作为WaitCallback方法的参数传入。
public delegate void WaitCallback(object state);
WaitCallback是一个委托类型,委托参数类型是object定义,因此传入WaitCallback的方法也应当是object类型。
codepublic static void DoWork(object state)
{// 执行一些操作,使用传递进来的状态对象
}static void Main(string[] args)
{// 将 DoWork 方法添加到线程池中ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), someStateObject);
}
someStateObject是DoWork的参数进行传入,然后开启线程。
2.SetMinThreads和SetMaxThreads
SetMinThreads和SetMaxThreads是线程池中最小线程数和最大线程数
// 参数:// workerThreads:// 要由线程池根据需要创建的新的最小工作程序线程数。// completionPortThreads:// 要由线程池根据需要创建的新的最小空闲异步 I/O 线程数。// 返回结果:如果更改成功,则为 true;否则为 false。[SecuritySafeCritical]public static bool SetMinThreads(int workerThreads, int completionPortThreads);// 参数:// workerThreads:// 线程池中辅助线程的最大数目。// completionPortThreads:// 线程池中异步 I/O 线程的最大数目。// 返回结果:如果更改成功,则为 true;否则为 false。[SecuritySafeCritical]public static bool SetMaxThreads(int workerThreads, int completionPortThreads)例如:ThreadPool.SetMinThreads(1,1);ThreadPool.SetMaxThreads(5, 5);
3.ManualResetEvent用法
1.ManualResetEvent 调用一次Set()后将允许恢复所有被阻塞线程。需手动在调用WaitOne()之后调用Reset()重置信号量状态为非终止,然后再次调用WaitOne()的时候才能继续阻塞线程,反之则不阻塞
2.AutoResetEvent,调用一次Set()只能继续被阻塞的一个线程,多次调用Set()才行,但不需手动调用Reset();再次调用WaitOne()的时候又能阻塞线程,也是和前者的区别
3.两者单个实例均可阻塞一个或多个线程,在多个线程中调用 主线程 创建的 两者单个实例.WaitOne(),前提是两者实例必须是非终止状态
4.两者实例化构造参数解释
public AutoResetEvent(bool initialState);
true:设置终止状态。相当于调用了Set(),即首次不会被WaitOne()阻塞,下次执行WaitOne()才会被阻塞
false:设置非终止状态。遇到WaitOne()立即阻塞所在的一个或多个线程
具体参考一下文章:
C#学习(二十八)——ManualResetEvent的理解和使用-CSDN博客
三、ThreadPool代码
代码1:关于ManualResetEvent用法
using System;
using System.Threading;public class Example
{// mre is used to block and release threads manually. It is// created in the unsignaled state.private static ManualResetEvent mre = new ManualResetEvent(false);static void Main(){Console.WriteLine("\nStart 3 named threads that block on a ManualResetEvent:\n");//中文注释1:开启三个线程,每个线程开启后调用WaitOne()阻塞。for(int i = 0; i <= 2; i++){Thread t = new Thread(ThreadProc);t.Name = "Thread_" + i;t.Start();}Thread.Sleep(500);Console.WriteLine("\nWhen all three threads have started, press Enter to call Set()" +"\nto release all the threads.\n");Console.ReadLine();//中文注释2:只有当Set()后才会执行WaitOne()后的代码mre.Set();Thread.Sleep(500);Console.WriteLine("\nWhen a ManualResetEvent is signaled, threads that call WaitOne()" +"\ndo not block. Press Enter to show this.\n");Console.ReadLine();//中文注释3:继续再开两个线程,仍然调用WaitOne(),但是不会阻塞,会继续执行for(int i = 3; i <= 4; i++){Thread t = new Thread(ThreadProc);t.Name = "Thread_" + i;t.Start();}Thread.Sleep(500);Console.WriteLine("\nPress Enter to call Reset(), so that threads once again block" +"\nwhen they call WaitOne().\n");Console.ReadLine();//中文注释4:只有Reset()后,下面再开线程就会继续被阻塞mre.Reset();// Start a thread that waits on the ManualResetEvent.Thread t5 = new Thread(ThreadProc);t5.Name = "Thread_5";t5.Start();Thread.Sleep(500);Console.WriteLine("\nPress Enter to call Set() and conclude the demo.");Console.ReadLine();//中文注释5:再次Set(),就可以了mre.Set();// If you run this example in Visual Studio, uncomment the following line://Console.ReadLine();}private static void ThreadProc(){string name = Thread.CurrentThread.Name;Console.WriteLine(name + " starts and calls mre.WaitOne()");mre.WaitOne();Console.WriteLine(name + " ends.");}
}/* This example produces output similar to the following:Start 3 named threads that block on a ManualResetEvent:Thread_0 starts and calls mre.WaitOne()
Thread_1 starts and calls mre.WaitOne()
Thread_2 starts and calls mre.WaitOne()When all three threads have started, press Enter to call Set()
to release all the threads.Thread_2 ends.
Thread_0 ends.
Thread_1 ends.When a ManualResetEvent is signaled, threads that call WaitOne()
do not block. Press Enter to show this.Thread_3 starts and calls mre.WaitOne()
Thread_3 ends.
Thread_4 starts and calls mre.WaitOne()
Thread_4 ends.Press Enter to call Reset(), so that threads once again block
when they call WaitOne().Thread_5 starts and calls mre.WaitOne()Press Enter to call Set() and conclude the demo.Thread_5 ends.
代码2:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleApplication1
{class Program{static void Main(string[] args){const int times = 10; //开线程数ManualResetEvent[] mre = new ManualResetEvent[times]; //1、定义开线程数Random random = new Random(); //随机数Console.WriteLine("开始 {0} 任务", times);for (int i = 0; i < times; i++) //2、循环这10个线程{mre[i] = new ManualResetEvent(false); //3、初始化每个线程:设置false表示无信号,将使WaitOne阻塞也就是线程等待count c = new count(random.Next(1, 1000), mre[i]); //借助类传参ThreadPool.QueueUserWorkItem(c.ThreadPoolCallback, i); //4、为每个线程安排任务}WaitHandle.WaitAll(mre); //6、让主线程等待所有线程完成(池中线程数不能多于64个)Console.WriteLine("所有线程完成!");Console.Read();}}class count{private int ramNum; //存放随机数private ManualResetEvent threadSta; //线程状态private int total; //存放线程计算结果/// <summary>/// 传递数据/// </summary>/// <param name="ramnum">保存随机数</param>/// <param name="mre">线程状态</param>public count(int ramnum, ManualResetEvent mre){ramNum = ramnum;threadSta = mre;}/// <summary>/// 线程/// </summary>/// <param name="threadParam"></param>public void ThreadPoolCallback(Object threadParam){int threadIndex = (int)threadParam;Console.WriteLine("线程 {0} 启动", threadIndex);total = docount(ramNum);Console.WriteLine("线程执行结果: {0}", total);threadSta.Set(); //5、设置每个线程为有信号状态:通知WaitOne不再阻塞}/// <summary>/// 从0开始加到传过来数/// </summary>/// <param name="ramNum">传过来的数:产生的随机数</param>/// <returns>返回相加的结果</returns>public int docount(int ramNum){int sum = 0;for (int i = 0; i <= ramNum; i++){sum += i;}return sum;}}
}
参考文献:
C#中的线程池使用方法_c# 线程池-CSDN博客
C#多线程--线程池(ThreadPool)_c# 主线程和 线程池-CSDN博客
C#知识点讲解之ManualResetEvent类的使用-CSDN博客
C#线程池实例(多参)_c# 线程池多参数-CSDN博客
C#多线程和线程池_c#线程池和线程的区别-CSDN博客
相关文章:
C#学习系列相关之多线程(五)----线程池ThreadPool用法
一、线程池的作用 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管…...

京东数据接口|电商运营中数据分析的重要性
在电商运营中,数据分析是非常重要的一环,它可以帮助电商企业更好地了解市场、了解消费者、了解产品、了解销售渠道等各种信息,从而制定更为科学有效的运营策略,提高销售效益。 数据方面用户可以直接选择使用数据接口来获取&#…...

C++入门(1)
目录 1.C关键字2.命名空间(namespace)2.1是什么2.2为什么2.3怎么用 3.C输入&输出4.缺省函数概念分类 5.函数重载6.引用6.1概念6.2特性6.3使用场景6.4引用和指针的不同点 1.C关键字 C总共有63个关键字 这里入门不多说,有需要的自行去了解 2.命名空间(namespac…...

redis-6.2.7 集群安装3主3从
因为资源有限准备了3 台 服务器,先查看防火墙的端口是否开放,如果没有开放先开放端口我使用的 6379 和 6380 这两个端口 所以将这两个端口放开。去redis 官网下载redis 安装包。下载地址 : redis 安装包下载 3. 安装redis 上传上去之后 3 台…...

【动态库】Ubuntu 添加动态库的搜索路径
在运行程序时,经常遇到下面这种动态库加载失败的情况,这时往往是系统在动态库的搜索路径下没有找到对应的库文件导致的。 目录 一、使用 LD_LIBRARY_PATH 二、修改 /etc/ld.so.conf 一、使用 LD_LIBRARY_PATH 环境变量 LD_LIBRARY_PATH是动态库的搜索…...

95740-26-4|用于体内DNA合成的探针F-ara-EdU
产品简介:(2S)-2-Deoxy-2-fluoro-5-ethynyluridine,一种用于体内DNA合成的探针,其毒性比EdU和BrdU都小。当需要延长细胞存活时间和不受干扰的细胞周期进展时,非常适合进行代谢DNA标记。 CAS号:95740-26-4 分子式&…...

Ajax使用流程
Ajax在不刷新页面的情况下,进行页面局部更新。 Ajax使用流程: 创建XmlHttpReqeust对象发送Ajax请求处理服务器响应 1. 创建XmlHttpReqeust对象 XmlHttpReqeust对象是Ajax的核心,使用该对象发起请求,接收响应 不同的浏览器创建…...

1808_ChibiOS基本的架构介绍
全部学习汇总: GreyZhang/g_ChibiOS: I found a new RTOS called ChibiOS and it seems interesting! (github.com) 简单看了一下ChibiOS的架构介绍,感觉这种OS以及组件非常适合快速构建一个应用。这里做一个简单的资料整理。。 1. 不同于其他的OS&#…...

曦力音视频转换工具Xilisoft Video Converter Ultimate mac中文版
Xilisoft Video Converter Ultimate mac是一款功能强大的视频转换软件,它可以将几乎所有流行的视频格式转换为其他格式,包括AVI、MPEG、WMV、DivX、MP4、H.264/AVC、AVCHD、MKV、RM、MOV、XviD、3GP等。此外,它还支持将视频转换为音频格式&am…...
Spring MVC 五:DispatcherServlet初始化之 mvc:annotation-driven
通过xml方式初始化DispatcherServlet时,xml文件中可以配置: <mvc:annotation-driven />或: <mvc:annotation-driven ><!--设置响应输出字符集--><mvc:message-converters><bean class"org.springframework.…...

uniapp EventChannel 页面跳转参数事件传递navigateBack,navigateTo 成功后通知事件区别
问题:navigateBack()emit事件在onload()监听不到 从A页面跳转到B页面,在B点击产生数据后,跳转回到A,并告诉A点击的数据是什么,使用: navigateBack()。 &…...
【C++ Primer Plus学习记录】指针——使用delete释放内存
当需要内存时,可以使用new来请求,使用完内存后,可以使用delete将其归还给内存池。 归还或释放(free)的内存可供程序的其他部分使用。 使用delete时,后面要加上指向内存块的指针(这些内存块最初…...
2023 NOIP A层联测9 - 风信子 题解
思路 我们可以考虑设 f l 0 , r 0 , l 1 , r 1 f_{l_0,r_0,l_1,r_1} fl0,r0,l1,r1 表示最大的 a l − a r a_l-a_r al−ar,其中 l ∈ [ l 0 , r 0 ] l\in [l_0,r_0] l∈[l0,r0], r ∈ [ l 1 , r 1 ] r\in [l_1, r_1] r∈[l1,r1…...

岩土工程安全监测无线振弦采集仪在无线组网的关键要点
岩土工程安全监测无线振弦采集仪在无线组网的关键要点 岩土工程是一种奇特而又极其重要的工程。它涉及到土地、岩石、气候等等因素,需要重视安全因素。而无线振弦采集仪作为一种常用的监测设备,可以采集岩土工程中的振动数据,从而确保工程的…...

代码随想录Day14 LeetCodeT110平衡二叉树 T257二叉树的所有路径 T404 左叶子之和
以下思路来自于: 代码随想录 (programmercarl.com) LeetCode T110 平衡二叉树 题目链接:110. 平衡二叉树 - 力扣(LeetCode) 题目思路 前面我们说过了,求二叉树的深度我们应该使用前序遍历,求二叉树的高度我们应该使用后序遍历,因为后序遍历可以将子树的…...

C语言自定义类型_枚举联合(3)
目录 枚举 什么是枚举类型? 枚举的声明 枚举的定义 枚举的优点 枚举的使用 联合(共用体) 什么是联合呢? 联合类型的定义 联合的特点 联合使用 联合大小的计算 联合的应用 今天接着我们来结束自定义类型。Ἑ…...

asp.net网上销售系统VS开发mysql数据库web结构c#编程Microsoft Visual Studio计算机毕业设计
一、源码特点 asp.net 网上销售系统 是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为mysql,使用c#语言开发 aspnet 网上销售系统1 二、功能介绍 前台功能…...

【Windows】RPC调用过程实例详解
概述:windows 创建 RPC调用过程实例详解 参考文章:Remote procedure call (RPC)(远程过程调用 (RPC)) - Win32 apps | Microsoft Learn 文章目录 0x01、生成 UUID 和模版(IDL)文件0x02、添加 acf 文件0x03、编译 idl 文件0x04、客…...

动手学强化学习第2章多臂老虎机
2.1简介 多臂老虎机问题可以被看作简化版的强化学习问题。但是其只有动作和奖励没有状态信息,算是简化版的强化学习问题。 2.2问题介绍 2.2.1问题定义 在多臂老虎机(MAB)问题中,有一个有K根拉杆的老虎机,拉动每一根拉杆都对应一个关于奖励…...

钡铼BL124EC实现EtherCAT转Ethernet/IP的优势
钡铼技术的BL124EC是一款用于将EtherCAT从站转换为Ethernet/IP从站的网关设备。它是钡铼技术开发的高性能、可靠的工业自动化通信解决方案之一。 添加图片注释,不超过 140 字(可选) BL124EC网关可以应用于多种工业自动化场景,以下…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...

【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...