CustomThreadPool.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Collections.Concurrent;
  7. using System.Threading;
  8. namespace HXX.Scanner.Biz
  9. {
  10. public class ThreadPool_manager
  11. {
  12. private static CustomThreadPool pool;
  13. public static void init()
  14. {
  15. pool = new CustomThreadPool(5);
  16. }
  17. public static void EnqueueTask(Action task)
  18. {
  19. pool.EnqueueTask(task);
  20. }
  21. }
  22. public class CustomThreadPool
  23. {
  24. #region 字段
  25. // 工作线程集合
  26. private readonly Thread[] _workerThreads;
  27. // 线程安全任务队列(存储要执行的任务)
  28. private readonly ConcurrentQueue<Action> _taskQueue = new ConcurrentQueue<Action>();
  29. // 线程同步信号:通知工作线程有新任务到来
  30. private readonly ManualResetEventSlim _taskSignal = new ManualResetEventSlim(false);
  31. // 标记线程池是否已释放
  32. private bool _isDisposed;
  33. #endregion
  34. #region 构造函数
  35. /// <summary>
  36. /// 初始化自定义线程池
  37. /// </summary>
  38. /// <param name="threadCount">工作线程数量(建议设置为 CPU 核心数)</param>
  39. public CustomThreadPool(int threadCount)
  40. {
  41. if (threadCount <= 0)
  42. throw new ArgumentOutOfRangeException(nameof(threadCount), "线程数量必须大于 0");
  43. // 创建固定数量的工作线程
  44. _workerThreads = new Thread[threadCount];
  45. for (int i = 0; i < threadCount; i++)
  46. {
  47. _workerThreads[i] = new Thread(WorkLoop)
  48. {
  49. IsBackground = true, // 后台线程:进程退出时自动终止
  50. Name = $"CustomPoolThread_{i}"
  51. };
  52. _workerThreads[i].Start();
  53. }
  54. }
  55. #endregion
  56. #region 核心方法
  57. /// <summary>
  58. /// 向线程池添加任务
  59. /// </summary>
  60. /// <param name="task">要执行的任务</param>
  61. public void EnqueueTask(Action task)
  62. {
  63. if (task == null)
  64. throw new ArgumentNullException(nameof(task));
  65. if (_isDisposed)
  66. throw new ObjectDisposedException(nameof(CustomThreadPool));
  67. // 加入任务队列
  68. _taskQueue.Enqueue(task);
  69. // 通知线程:有新任务可以执行
  70. _taskSignal.Set();
  71. }
  72. /// <summary>
  73. /// 工作线程主循环(持续从队列取任务执行)
  74. /// </summary>
  75. private void WorkLoop()
  76. {
  77. while (!_isDisposed)
  78. {
  79. // 等待任务信号(无任务时阻塞,不占用 CPU)
  80. _taskSignal.Wait();
  81. // 线程池已关闭,退出循环
  82. if (_isDisposed)
  83. break;
  84. // 尝试从队列取出任务并执行
  85. if (_taskQueue.TryDequeue(out Action task))
  86. {
  87. try
  88. {
  89. task.Invoke(); // 执行任务
  90. }
  91. catch
  92. {
  93. // 这里可以添加任务异常日志(避免单个任务崩溃整个线程)
  94. }
  95. }
  96. else
  97. {
  98. // 队列空了,重置信号,进入等待状态
  99. _taskSignal.Reset();
  100. }
  101. }
  102. }
  103. #endregion
  104. #region 释放资源
  105. /// <summary>
  106. /// 关闭线程池,释放所有资源
  107. /// </summary>
  108. public void Dispose()
  109. {
  110. if (_isDisposed)
  111. return;
  112. _isDisposed = true;
  113. _taskSignal.Set(); // 唤醒所有等待的线程
  114. // 等待所有工作线程退出
  115. foreach (Thread thread in _workerThreads)
  116. {
  117. thread.Join();
  118. }
  119. _taskSignal.Dispose();
  120. }
  121. #endregion
  122. }
  123. }