野生程序员对.NETFramework 4.0 ThreadPool的理解
ThreadPool 类
提供一个线程池,该线程池可用于执行任务、发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。
命名空间: System.Threading
程序集: mscorlib(位于 mscorlib.dll)版本信息
.NET Framework
自 1.1 起可用
可移植类库
在 可移植 .NET 平台 中受支持
Silverlight
自 2.0 起可用
Windows Phone Silverlight
自 7.0 起可用
一边说着要用技术安身立命,一边感叹自己的野生属性。好吧,知之为知之,不知就不知。我"以为"是这样这样那样那样,这样说真是没意思。现在的疑惑有以下几点:
- 1、线程池内部有几个工作线程?
- 2、使用线程池的正确姿势(场景和控制)?
- 3、有必要自己封装一个不?
开始看MSDN文档
1 2 3 | [HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true , ExternalThreading = true )] public static class ThreadPool |
方法
伪代码
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 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 | #region 程序集 mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 // C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll #endregion using System.Runtime.InteropServices; using System.Security; namespace System.Threading { // // 摘要: // 提供一个线程池,该线程池可用于发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。 public static class ThreadPool { // // 摘要: // 将操作系统句柄绑定到 System.Threading.ThreadPool。 // // 参数: // osHandle: // 保存操作系统句柄的 System.Runtime.InteropServices.SafeHandle。在非托管端必须为重叠 I/O 打开该句柄。 // // 返回结果: // 如果绑定了句柄,则为 true;否则为 false。 // // 异常: // T:System.ArgumentNullException: // osHandle 为 null。 [SecuritySafeCritical] public static bool BindHandle(SafeHandle osHandle); // // 摘要: // 将操作系统句柄绑定到 System.Threading.ThreadPool。 // // 参数: // osHandle: // 持有句柄的 System.IntPtr。在非托管端必须为重叠 I/O 打开该句柄。 // // 返回结果: // 如果绑定了句柄,则为 true;否则为 false。 // // 异常: // T:System.Security.SecurityException: // 调用方没有所要求的权限。 [Obsolete( "ThreadPool.BindHandle(IntPtr) has been deprecated. Please use ThreadPool.BindHandle(SafeHandle) instead." , false )] [SecuritySafeCritical] public static bool BindHandle(IntPtr osHandle); // // 摘要: // 检索由 System.Threading.ThreadPool.GetMaxThreads(System.Int32@,System.Int32@) 方法返回的最大线程池线程数和当前活动线程数之间的差值。 // // 参数: // workerThreads: // 可用辅助线程的数目。 // // completionPortThreads: // 可用异步 I/O 线程的数目。 [SecuritySafeCritical] public static void GetAvailableThreads( out int workerThreads, out int completionPortThreads); // // 摘要: // 检索可以同时处于活动状态的线程池请求的数目。所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。 // // 参数: // workerThreads: // 线程池中辅助线程的最大数目。 // // completionPortThreads: // 线程池中异步 I/O 线程的最大数目。 [SecuritySafeCritical] public static void GetMaxThreads( out int workerThreads, out int completionPortThreads); // // 摘要: // 检索线程池在新请求预测中维护的空闲线程数。 // // 参数: // workerThreads: // 当前由线程池维护的空闲辅助线程的最小数目。 // // completionPortThreads: // 当前由线程池维护的空闲异步 I/O 线程的最小数目。 [SecuritySafeCritical] public static void GetMinThreads( out int workerThreads, out int completionPortThreads); // // 摘要: // 将方法排入队列以便执行。此方法在有线程池线程变得可用时执行。 // // 参数: // callBack: // 一个 System.Threading.WaitCallback,表示要执行的方法。 // // 返回结果: // 如果此方法成功排队,则为 true;如果未能将该工作项排队,则引发 System.NotSupportedException。 // // 异常: // T:System.ArgumentNullException: // callBack 为 null。 // // T:System.NotSupportedException: // 承载公共语言运行时 (CLR) 的宿主不支持此操作。 [SecuritySafeCritical] public static bool QueueUserWorkItem(WaitCallback callBack); // // 摘要: // 将方法排入队列以便执行,并指定包含该方法所用数据的对象。此方法在有线程池线程变得可用时执行。 // // 参数: // callBack: // System.Threading.WaitCallback,它表示要执行的方法。 // // state: // 包含方法所用数据的对象。 // // 返回结果: // 如果此方法成功排队,则为 true;如果未能将该工作项排队,则引发 System.NotSupportedException。 // // 异常: // T:System.NotSupportedException: // 承载公共语言运行时 (CLR) 的宿主不支持此操作。 // // T:System.ArgumentNullException: // callBack 为 null。 [SecuritySafeCritical] public static bool QueueUserWorkItem(WaitCallback callBack, object state); // // 摘要: // 注册一个等待 System.Threading.WaitHandle 的委托,并指定一个 System.TimeSpan 值来表示超时时间。 // // 参数: // waitObject: // 要注册的 System.Threading.WaitHandle。使用 System.Threading.WaitHandle 而非 System.Threading.Mutex。 // // callBack: // waitObject 参数终止时调用的 System.Threading.WaitOrTimerCallback 委托。 // // state: // 传递给委托的对象。 // // timeout: // System.TimeSpan 表示的超时时间。如果 timeout 为 0(零),则函数将测试对象的状态并立即返回。如果 timeout 为 -1,则函数的超时间隔永远不过期。 // // executeOnlyOnce: // 如果为 true,表示在调用了委托后,线程将不再在 waitObject 参数上等待;如果为 false,表示每次完成等待操作后都重置计时器,直到注销等待。 // // 返回结果: // 封装本机句柄的 System.Threading.RegisteredWaitHandle。 // // 异常: // T:System.ArgumentOutOfRangeException: // timeout 参数小于 -1。 // // T:System.NotSupportedException: // timeout 参数大于 System.Int32.MaxValue。 [SecuritySafeCritical] public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, TimeSpan timeout, bool executeOnlyOnce); // // 摘要: // 注册一个等待 System.Threading.WaitHandle 的委托,并指定一个 64 位有符号整数来表示超时值(以毫秒为单位)。 // // 参数: // waitObject: // 要注册的 System.Threading.WaitHandle。使用 System.Threading.WaitHandle 而非 System.Threading.Mutex。 // // callBack: // waitObject 参数终止时调用的 System.Threading.WaitOrTimerCallback 委托。 // // state: // 传递给委托的对象。 // // millisecondsTimeOutInterval: // 以毫秒为单位的超时。如果 millisecondsTimeOutInterval 参数为 0(零),函数将测试对象的状态并立即返回。如果 millisecondsTimeOutInterval // 为 -1,则函数的超时间隔永远不过期。 // // executeOnlyOnce: // 如果为 true,表示在调用了委托后,线程将不再在 waitObject 参数上等待;如果为 false,表示每次完成等待操作后都重置计时器,直到注销等待。 // // 返回结果: // 封装本机句柄的 System.Threading.RegisteredWaitHandle。 // // 异常: // T:System.ArgumentOutOfRangeException: // millisecondsTimeOutInterval 参数小于 -1。 [SecuritySafeCritical] public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce); // // 摘要: // 注册一个等待 System.Threading.WaitHandle 的委托,并指定一个 32 位有符号整数来表示超时值(以毫秒为单位)。 // // 参数: // waitObject: // 要注册的 System.Threading.WaitHandle。使用 System.Threading.WaitHandle 而非 System.Threading.Mutex。 // // callBack: // waitObject 参数终止时调用的 System.Threading.WaitOrTimerCallback 委托。 // // state: // 传递给委托的对象。 // // millisecondsTimeOutInterval: // 以毫秒为单位的超时。如果 millisecondsTimeOutInterval 参数为 0(零),函数将测试对象的状态并立即返回。如果 millisecondsTimeOutInterval // 为 -1,则函数的超时间隔永远不过期。 // // executeOnlyOnce: // 如果为 true,表示在调用了委托后,线程将不再在 waitObject 参数上等待;如果为 false,表示每次完成等待操作后都重置计时器,直到注销等待。 // // 返回结果: // 封装本机句柄的 System.Threading.RegisteredWaitHandle。 // // 异常: // T:System.ArgumentOutOfRangeException: // millisecondsTimeOutInterval 参数小于 -1。 [SecuritySafeCritical] public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce); // // 摘要: // 指定表示超时(以毫秒为单位)的 32 位无符号整数,注册一个委托等待 System.Threading.WaitHandle。 // // 参数: // waitObject: // 要注册的 System.Threading.WaitHandle。使用 System.Threading.WaitHandle 而非 System.Threading.Mutex。 // // callBack: // waitObject 参数终止时调用的 System.Threading.WaitOrTimerCallback 委托。 // // state: // 传递给委托的对象。 // // millisecondsTimeOutInterval: // 以毫秒为单位的超时。如果 millisecondsTimeOutInterval 参数为 0(零),函数将测试对象的状态并立即返回。如果 millisecondsTimeOutInterval // 为 -1,则函数的超时间隔永远不过期。 // // executeOnlyOnce: // 如果为 true,表示在调用了委托后,线程将不再在 waitObject 参数上等待;如果为 false,表示每次完成等待操作后都重置计时器,直到注销等待。 // // 返回结果: // System.Threading.RegisteredWaitHandle,可用于取消已注册的等待操作。 // // 异常: // T:System.ArgumentOutOfRangeException: // millisecondsTimeOutInterval 参数小于 -1。 [CLSCompliant( false )] [SecuritySafeCritical] public static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce); // // 摘要: // 设置可以同时处于活动状态的线程池的请求数目。所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。 // // 参数: // workerThreads: // 线程池中辅助线程的最大数目。 // // completionPortThreads: // 线程池中异步 I/O 线程的最大数目。 // // 返回结果: // 如果更改成功,则为 true;否则为 false。 [SecuritySafeCritical] public static bool SetMaxThreads( int workerThreads, int completionPortThreads); // // 摘要: // 设置线程池在新请求预测中维护的空闲线程数。 // // 参数: // workerThreads: // 要由线程池维护的新的最小空闲辅助线程数。 // // completionPortThreads: // 要由线程池维护的新的最小空闲异步 I/O 线程数。 // // 返回结果: // 如果更改成功,则为 true;否则为 false。 [SecuritySafeCritical] public static bool SetMinThreads( int workerThreads, int completionPortThreads); // // 摘要: // 将重叠的 I/O 操作排队以便执行。 // // 参数: // overlapped: // 要排队的 System.Threading.NativeOverlapped 结构。 // // 返回结果: // 如果成功地将此操作排队到 I/O 完成端口,则为 true;否则为 false。 [CLSCompliant( false )] [SecurityCritical] public static bool UnsafeQueueNativeOverlapped(NativeOverlapped* overlapped); // // 摘要: // 将指定的委托排队到线程池,但不会将调用堆栈传播到辅助线程。 // // 参数: // callBack: // 一个 System.Threading.WaitCallback,表示当线程池中的线程选择工作项时调用的委托。 // // state: // 在接受线程池服务时传递给委托的对象。 // // 返回结果: // 如果方法成功,则为 true;如果未能将该工作项排队,则引发 System.OutOfMemoryException。 // // 异常: // T:System.Security.SecurityException: // 调用方没有所要求的权限。 // // T:System.ApplicationException: // 遇到了内存不足的情况。 // // T:System.OutOfMemoryException: // 未能将该工作项排队。 // // T:System.ArgumentNullException: // callBack 为 null。 [SecurityCritical] public static bool UnsafeQueueUserWorkItem(WaitCallback callBack, object state); // // 摘要: // 注册一个等待 System.Threading.WaitHandle 的委托,并指定一个 64 位有符号整数来表示超时值(以毫秒为单位)。不将调用堆栈传播到辅助线程。 // // 参数: // waitObject: // 要注册的 System.Threading.WaitHandle。使用 System.Threading.WaitHandle 而非 System.Threading.Mutex。 // // callBack: // waitObject 参数终止时调用的委托。 // // state: // 传递给委托的对象。 // // millisecondsTimeOutInterval: // 以毫秒为单位的超时。如果 millisecondsTimeOutInterval 参数为 0(零),函数将测试对象的状态并立即返回。如果 millisecondsTimeOutInterval // 为 -1,则函数的超时间隔永远不过期。 // // executeOnlyOnce: // 如果为 true,表示在调用了委托后,线程将不再在 waitObject 参数上等待;如果为 false,表示每次完成等待操作后都重置计时器,直到注销等待。 // // 返回结果: // System.Threading.RegisteredWaitHandle 对象,可用于取消已注册的等待操作。 // // 异常: // T:System.ArgumentOutOfRangeException: // millisecondsTimeOutInterval 参数小于 -1。 // // T:System.Security.SecurityException: // 调用方没有所要求的权限。 [SecurityCritical] public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce); // // 摘要: // 指定表示超时(以毫秒为单位)的 32 位无符号整数,注册一个委托等待 System.Threading.WaitHandle。不将调用堆栈传播到辅助线程。 // // 参数: // waitObject: // 要注册的 System.Threading.WaitHandle。使用 System.Threading.WaitHandle 而非 System.Threading.Mutex。 // // callBack: // waitObject 参数终止时调用的委托。 // // state: // 传递给委托的对象。 // // millisecondsTimeOutInterval: // 以毫秒为单位的超时。如果 millisecondsTimeOutInterval 参数为 0(零),函数将测试对象的状态并立即返回。如果 millisecondsTimeOutInterval // 为 -1,则函数的超时间隔永远不过期。 // // executeOnlyOnce: // 如果为 true,表示在调用了委托后,线程将不再在 waitObject 参数上等待;如果为 false,表示每次完成等待操作后都重置计时器,直到注销等待。 // // 返回结果: // System.Threading.RegisteredWaitHandle 对象,可用于取消已注册的等待操作。 // // 异常: // T:System.Security.SecurityException: // 调用方没有所要求的权限。 [CLSCompliant( false )] [SecurityCritical] public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce); // // 摘要: // 注册一个等待 System.Threading.WaitHandle 的委托,并指定一个 System.TimeSpan 值来表示超时时间。不将调用堆栈传播到辅助线程。 // // 参数: // waitObject: // 要注册的 System.Threading.WaitHandle。使用 System.Threading.WaitHandle 而非 System.Threading.Mutex。 // // callBack: // waitObject 参数终止时调用的委托。 // // state: // 传递给委托的对象。 // // timeout: // System.TimeSpan 表示的超时时间。如果 timeout 为 0(零),则函数将测试对象的状态并立即返回。如果 timeout 为 -1,则函数的超时间隔永远不过期。 // // executeOnlyOnce: // 如果为 true,表示在调用了委托后,线程将不再在 waitObject 参数上等待;如果为 false,表示每次完成等待操作后都重置计时器,直到注销等待。 // // 返回结果: // System.Threading.RegisteredWaitHandle 对象,可用于取消已注册的等待操作。 // // 异常: // T:System.ArgumentOutOfRangeException: // timeout 参数小于 -1。 // // T:System.NotSupportedException: // timeout 参数大于 System.Int32.MaxValue。 // // T:System.Security.SecurityException: // 调用方没有所要求的权限。 [SecurityCritical] public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, TimeSpan timeout, bool executeOnlyOnce); // // 摘要: // 注册一个等待 System.Threading.WaitHandle 的委托,并使用一个 32 位带符号整数来表示超时时间(以毫秒为单位)。不将调用堆栈传播到辅助线程。 // // 参数: // waitObject: // 要注册的 System.Threading.WaitHandle。使用 System.Threading.WaitHandle 而非 System.Threading.Mutex。 // // callBack: // waitObject 参数终止时调用的委托。 // // state: // 传递给委托的对象。 // // millisecondsTimeOutInterval: // 以毫秒为单位的超时。如果 millisecondsTimeOutInterval 参数为 0(零),函数将测试对象的状态并立即返回。如果 millisecondsTimeOutInterval // 为 -1,则函数的超时间隔永远不过期。 // // executeOnlyOnce: // 如果为 true,表示在调用了委托后,线程将不再在 waitObject 参数上等待;如果为 false,表示每次完成等待操作后都重置计时器,直到注销等待。 // // 返回结果: // System.Threading.RegisteredWaitHandle 对象,可用于取消已注册的等待操作。 // // 异常: // T:System.ArgumentOutOfRangeException: // millisecondsTimeOutInterval 参数小于 -1。 // // T:System.Security.SecurityException: // 调用方没有所要求的权限。 [SecurityCritical] public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce); } } |
“承载公共语言运行时 (CLR) 的宿主不支持此操作”出现了好多次吧。试试反编译mscorlib.dll,看看有什么发现。
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 | [SecurityCritical, SuppressUnmanagedCodeSecurity] [DllImport( "QCall" , CharSet = CharSet.Unicode)] internal static extern bool AdjustThreadsInPool( uint QueueLength); [CLSCompliant( false ), SecurityCritical] public unsafe static bool UnsafeQueueNativeOverlapped(NativeOverlapped* overlapped) { } [SecurityCritical, SuppressUnmanagedCodeSecurity] [DllImport( "QCall" , CharSet = CharSet.Unicode)] internal static extern bool ShouldUseNewWorkerPool(); [SecurityCritical, SuppressUnmanagedCodeSecurity] [DllImport( "QCall" , CharSet = CharSet.Unicode)] internal static extern bool CompleteThreadPoolRequest( uint QueueLength); [SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal static extern bool NotifyWorkItemComplete(); [SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void ReportThreadStatus( bool isWorking); [SecuritySafeCritical] internal static void NotifyWorkItemProgress() { } [SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void NotifyWorkItemProgressNative(); [SecurityCritical, SuppressUnmanagedCodeSecurity] [DllImport( "QCall" , CharSet = CharSet.Unicode)] internal static extern bool ShouldReturnToVm(); [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), SecurityCritical, SuppressUnmanagedCodeSecurity] [DllImport( "QCall" , CharSet = CharSet.Unicode)] internal static extern bool SetAppDomainRequestActive(); [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), SecurityCritical, SuppressUnmanagedCodeSecurity] [DllImport( "QCall" , CharSet = CharSet.Unicode)] internal static extern void ClearAppDomainRequestActive(); [SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal static extern bool IsThreadPoolHosted(); [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), SecurityCritical] [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void SetNativeTpEvent(); |
[MethodImplAttribute(MethodImplOptions.Synchronized)]标签应用到实例方法,相当于对当前实例加锁 lock(this)
[MethodImplAttribute(MethodImplOptions.Synchronized)]标签应用到静态方法,相当于当前类型加锁。如 WithDraw 是静态方法,就相当于 lock (typeof(Account))
接下来我们再来看看SynchronizationAttribute类:
MSDN对SynchronizationAttribute的解释为:为当前上下文和所有共享同一实例的上下文强制一个同步域。
SynchronizationAttribute 的类:一个在 System.Runtime.Remoting.Contexts 命名空间中,另一个在 System.EnterpriseServices 命名空间中。System.EnterpriseServices.SynchronizationAttribute 类仅支持同步调用,并且只可与接受服务的组件一起使用。System.Runtime.Remoting.Contexts.SynchronizationAttribute 同时支持同步调用和异步调用,并且只可与上下文绑定对象一起使用。
毛发现都没有,看来还是功力尚浅,资质平庸啊。发现了一堆空方法,什么鬼?都是没有具体实现的。看来先猜上一猜了:SetMaxThreads和SetMinThreads说明可以设置工作线程的数量,线程的内部使用了完成端口(没文化的我理解为ConcurrentQueue,大白话就是说是一个线程安全的队列)。那么完成端口编程模式号称是windows系统最优秀的编程模型,会不会非常智能呢?是不是不调用SetMaxThreads和SetMinThreads操作系统就根据你机器的CPU核心数来自己设定最大值呢?
回到前面的几个问题,偶还是搞不清楚啊。谁能告诉我,什么是什么,什么是什么...咦,这兄台唱上了吧。^_^
反编译大神实现的CoreThreadPool
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 | 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(); } } } |
经过几个小时测试,最终得出一个结论:ThreadPool的性能已经上了天。微软威武!不用再去重复造轮子了。这个线程池的使用场景是生产线上的高速生产线的采集器上用的,毫秒级别的,但也是1秒几十个产品而已。
测试代码
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 | class Program { private static Stopwatch sw = new Stopwatch(); static void Main( string [] args) { int id = Thread.CurrentThread.ManagedThreadId; Console.WriteLine( "CurrentThread.ManagedThreadId是:" + id.ToString()); ThreadPool.QueueUserWorkItem(Pool_Exceute, null ); Action task = () => { Thread thread = new Thread(() => { while ( true ) { object queueObj; queueObj = ( object )DateTime.Now.Ticks; sw.Reset(); sw.Start(); if (ThreadPool.QueueUserWorkItem(Pool_Exceute, queueObj)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(DateTime.Now + "->成功抛入队列,抛入的委托对象的参数是:" + queueObj.ToString()); } Thread.Sleep(1); } }); thread.Start(); }; Parallel.Invoke(task, task, task, task, task); Console.ReadLine(); } private static void Pool_Exceute( object obj) { if (obj != null ) { Console.ResetColor(); int id = Thread.CurrentThread.ManagedThreadId; Console.WriteLine( "CurrentThread.ManagedThreadId是:" + id.ToString()); Console.WriteLine(DateTime.Now + "->委托对象是:" + obj.ToString()); int workThread_Count = 0; int id_IOCP = 0; ThreadPool.GetMaxThreads( out workThread_Count, out id_IOCP); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(DateTime.Now + string .Format( "->线程池最大工作线程数是{0}.当前完成端口的ID是{1}." , workThread_Count, id_IOCP)); ThreadPool.GetAvailableThreads( out workThread_Count, out id_IOCP); Console.WriteLine(DateTime.Now + string .Format( "->线程池当前可用的工作线程数是{0}.当前完成端口的ID是{1}." , workThread_Count, id_IOCP)); sw.Stop(); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine( "从入队到出队耗时:" + sw.ElapsedMilliseconds); sw.Reset(); } } } |
作者:数据酷软件
出处:https://www.cnblogs.com/datacool/p/datacool_ThreadPool_2017.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语句:使用策略模式优化代码结构