自动化控制之线程池的使用
昨天反编译看了公司项目首席架构师实现的线程池。非常之惊讶,在没有.net 4可用的年代。那思想和那技术是相当的可以啊。佩服。
这里说的线程池是一个类我总觉得这样叫有点不名副其实。其实就是一个类内部实现了FIFO队列,把临时数据放到这个队列里,“线程池类”按照入队的先后次序触发一个负责解析校验等的事件,并且把数据传递个这个事件。
好了,上代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | /// <summary> /// 自定义线程池类,不依赖.net Queue实现了先进先出处理队列里数据 /// </summary> public class CoreThreadPool : IDisposable { /// <summary> /// 队列元素申明 /// </summary> [StructLayout(LayoutKind.Sequential)] private class PoolData { /// <summary> /// 外部要求放入队列的数据 /// </summary> public object Data; /// <summary> /// 需要执行的命令(Exit/Command(自定义)) /// </summary> public CoreThreadPool.PoolCommand Command; public PoolData() { this .Command = CoreThreadPool.PoolCommand.Exit; } public PoolData( object data) { this .Data = data; this .Command = CoreThreadPool.PoolCommand.Command; } public PoolData(CoreThreadPool.PoolCommand cmd) { this .Command = cmd; } } protected enum PoolCommand { Command, Exit } protected SafeFileHandle complatePort; /// <summary> /// 线程池主线程 /// </summary> protected Thread thread; protected volatile bool isOpened; [method: CompilerGenerated] [CompilerGenerated] public event Action< object > Exceute; [method: CompilerGenerated] [CompilerGenerated] public event Action< object > ExitExceute; /// <summary> /// 线程池是否正在运行 /// </summary> public bool IsOpened { get { return this .isOpened; } set { this .isOpened = value; } } [DllImport( "kernel32.dll" , CharSet = CharSet.Auto, SetLastError = true )] private static extern SafeFileHandle CreateIoCompletionPort(IntPtr FileHandle, IntPtr ExistingCompletionPort, IntPtr CompletionKey, uint NumberOfConcurrentThreads); [DllImport( "kernel32.dll" , CharSet = CharSet.Auto, SetLastError = true )] private static extern bool GetQueuedCompletionStatus(SafeFileHandle CompletionPort, out uint lpNumberOfBytesTransferred, out IntPtr lpCompletionKey, out IntPtr lpOverlapped, uint dwMilliseconds); [DllImport( "Kernel32" , CharSet = CharSet.Auto)] private static extern bool PostQueuedCompletionStatus(SafeFileHandle CompletionPort, uint dwNumberOfBytesTransferred, IntPtr dwCompletionKey, IntPtr lpOverlapped); /// <summary> /// 启动线程池的主线程 /// </summary> public void Start() { isOpened = true ; if (thread != null ) { throw new Exception( "线程池已经是启动状态!" ); } complatePort = CreateIoCompletionPort( new IntPtr(-1), IntPtr.Zero, IntPtr.Zero, 0u); if (complatePort.IsInvalid) { throw new Exception( string .Format( "创建IOCP出错!原因是:{0}" , Marshal.GetLastWin32Error().ToString())); } thread = new Thread( new ParameterizedThreadStart( this .Run)); thread.Start(complatePort); } /// <summary> /// 外部提交数据对象到队列 /// </summary> /// <param name="data"></param> public void Post( object data) { PostData( new CoreThreadPool.PoolData(data)); } /// <summary> /// 线程池主线程执行逻辑 /// </summary> /// <param name="CompletionPortID"></param> private void Run( object CompletionPortID) { SafeFileHandle completionPort = (SafeFileHandle)CompletionPortID; while (IsOpened) { uint num; IntPtr intPtr; IntPtr value; //从队列里取出最前面的对象 CoreThreadPool.GetQueuedCompletionStatus(completionPort, out num, out intPtr, out value, 4294967295u); if (num > 0u) { GCHandle gCHandle = GCHandle.FromIntPtr(value); CoreThreadPool.PoolData poolData = (CoreThreadPool.PoolData)gCHandle.Target; gCHandle.Free(); if (poolData.Command != CoreThreadPool.PoolCommand.Command) { IsOpened = false ; break ; } RaiseExecute(poolData.Data); } } RaiseExitExecute( "线程池已经停止。" ); isOpened = false ; thread = null ; } /// <summary> /// 触发Execute事件 /// </summary> /// <param name="data"></param> private void RaiseExecute( object data) { Exceute?.Invoke(data); } /// <summary> /// 触发ExitExecute事件 /// </summary> /// <param name="data"></param> private void RaiseExitExecute( object data) { ExitExceute?.Invoke(data); } /// <summary> /// 结束线程池主线程 /// </summary> public void Stop() { PostData( new PoolData(PoolCommand.Exit)); IsOpened = false ; } /// <summary> /// 内部提交数据到线程池队列中 /// </summary> /// <param name="data"></param> private void PostData(PoolData data) { if (complatePort.IsClosed) { return ; } GCHandle value = GCHandle.Alloc(data); PostQueuedCompletionStatus(complatePort, ( uint )IntPtr.Size, IntPtr.Zero, GCHandle.ToIntPtr(value)); } public void Dispose() { if ( this .thread != null && this .thread.ThreadState != System.Threading.ThreadState.Stopped) { this .Stop(); } } } |
代码亮点:队列是使用操作系统的,使用windows api实现的。牛吧。
由于现在项目已经依赖.net 4了。于是进行了模仿,经过一番测试,发现差不多,不过还是觉得在多线程环境下使用 ConcurrentQueue会更好些呢。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | /// <summary> /// 自定义线程池类,使用ConcurrentQueue实现了先进先出处理队列里数据 /// </summary> public class CoolThreadPool<T> { protected ConcurrentQueue<T> queue = new ConcurrentQueue<T>(); protected Thread thread; private volatile bool isOpened; public bool IsOpened { get { return isOpened; } } public event Action<T> Exceute; public event Action StopedExceute; /// <summary> /// 启动线程池的主线程 /// </summary> public void Start() { if (thread != null ) { throw new Exception( "线程池已经是启动状态!" ); } thread = new Thread(Run); thread.Start(); isOpened = thread != null ; } /// <summary> /// 线程池主线程执行逻辑 /// </summary> private void Run() { while (isOpened) { T temp; queue.TryDequeue( out temp); if (temp != null ) { RaiseExecute(temp); } else break ; } isOpened = false ; thread = null ; RaiseStopedExceute(); } /// <summary> /// 触发Execute事件 /// </summary> /// <param name="data"></param> private void RaiseExecute(T data) { Exceute?.Invoke(data); } /// <summary> /// 触发停止Execute事件 /// </summary> /// <param name="data"></param> private void RaiseStopedExceute() { StopedExceute?.Invoke(); } /// <summary> /// 结束线程池主线程 /// </summary> public void Stop() { PostData( default (T)); isOpened = false ; } /// <summary> /// 外部提交数据对象到队列 /// </summary> /// <param name="data"></param> public void Post(T data) { PostData(data); } /// <summary> /// 内部提交数据到线程池队列中 /// </summary> /// <param name="data"></param> private void PostData(T data) { queue.Enqueue(data); } public void Dispose() { if ( this .thread != null && this .thread.ThreadState != System.Threading.ThreadState.Stopped) { this .Stop(); } } } |
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | string [] temp = new string [] { "This is 1." , "This is 2." , "This is 3." , "This is 4." , "This is 5." , "This is 6." , "This is 7." , "This is 8." , "This is 9." , "This is 10." , "This is 11." , "This is 12." }; pool.Exceute += Pool_Exceute1; pool.Start(); foreach ( string data in temp) { pool.Post(data); } |
作者:数据酷软件
出处:https://www.cnblogs.com/datacool/p/datacool_threadpool.html
关于作者:20年编程从业经验,持续关注MES/ERP/POS/WMS/工业自动化
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明。
联系方式: qq:71008973;wx:6857740733
基于人脸识别的考勤系统 地址: https://gitee.com/afeng124/viewface_attendance_ext
自己开发安卓应用框架 地址: https://gitee.com/afeng124/android-app-frame
WPOS(warehouse+pos) 后台演示地址: http://47.239.106.75:8080/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构