C#多线程处理多个队列数据的方法

许南星
许南星
发布时间:2026-10-13 | 5人浏览过
原创

本文分享一种使用C#多线程处理多个队列数据的示例方法。通过主线程持续生成随机数推入初始队列,并由两个工作线程依次从队列中取出数据进行级联处理(Queue1→Queue2→Queue3),利用线程池(ThreadPool)进行资源调度,并在处理过程中实时更新界面显示各队列状态。

C#多线程处理多队列的实现思路

在处理需要流水线式或分阶段处理的队列数据时,使用多线程配合全局队列变量是一种直观的做法。本例旨在演示如何利用 System.Threading 命名空间下的线程池功能,协调不同队列间的数据流转与状态监控。

第1步:定义共享状态与代理方法

首先,建立用于界面交互的委托类型以及控制程序生命周期的标志位。代码中使用了静态变量来模拟一个测试环境的全局上下文。

  • 代理方法类型定义: 创建一个名为 DelegateShowStateInfo 的委托,用于更新UI显示。
  • 生命周期标记: 定义 _Exit 布尔值,作为所有线程终止的共同信号。
//用于顯示狀態的代理方法類型定義 
public delegate void DelegateShowStateInfo(string state); 
//... 内部类声明部分 ... 

第2步:初始化全局队列容器

为了存储待处理及已处理的数据,定义了三个静态队列集合。这里为了简化演示,使用了 ArrayList 类型(注:在实际现代开发中,推荐使用泛型 List<T> 以提供更好的类型安全)。

private static IList _Queue1 = new ArrayList(); //Queue1的數據 
private static IList _Queue2 = new ArrayList(); //Queue2的數據 
private static IList _Queue3 = new ArrayList(); //Queue3的數據 

第3步:配置并启动线程池任务

在 Testing 方法中,将当前窗体引用和方法传入后,通过 ThreadPool.QueueUserWorkItem 启动三个后台任务。这种方式让操作系统自动分配线程资源,避免了手动创建线程的高开销。

  1. 主测试线程 (MainTestThread): 负责源源不断地产生随机数据。
  2. 队列处理线程1 (Queue1Thread): 消费 Queue1 并将结果推入 Queue2。
  3. 队列处理线程2 (Queue2Thread): 消费 Queue2 并将结果推入 Queue3。
public static void Testing(Form sender, DelegateShowStateInfo method)
{
  _StateMethod = method;
  _OwnerForm = sender;
  _Exit = false; // 重置退出标志
  ThreadPool.QueueUserWorkItem(MainTestThread);
  ThreadPool.QueueUserWorkItem(Queue1Thread); //啟動Queue1線程 
  ThreadPool.QueueUserWorkItem(Queue2Thread); //啟動Queue2線程 
}

第4步:主线程循环压入数据

MainTestThread 在一个大的 while 循环中运行,直到收到退出信号。每次循环生成一个随机数,将其添加到 _Queue1 末尾,并调用 Application.DoEvents() 让UI保持响应,同时短暂休眠以避免CPU占用过高。

//測試用的主線程,循環向隊列1中壓入數據。 
public static void MainTestThread(object state)
{
  Random R = new Random(1);
  double V = 0;
  while (_Exit == false)
  {
    //臨時數據,隨機數 
    V = R.NextDouble();
    _Queue1.Add(V); //把數據插入到隊列1 
    Application.DoEvents();
    ShowState();
    Thread.Sleep(100);//生成隨機數太快,為了看清效果,暫停n毫秒 
  }
}

第5步:依次处理队列间的流转

这是核心逻辑所在的步骤。每个工作线程都包含一个内层循环,专门检查其负责的源队列是否为空。

  • Queue1Thread 逻辑: 只要 _Queue1.Count > 0,就取出第一个元素 (_Queue1[0]) 并从头部移除 (_Queue1.RemoveAt(0)),然后放入 _Queue2。
  • Queue2Thread 逻辑: 同理,从 _Queue2 取数放入 _Queue3。

注意:RemoveAt(0) 对非泛型列表操作效率较低,实际项目中建议使用专业的并发队列(如 ConcurrentQueue<T>)。

//对queue1中的数据进行处理,处理后放到queue2中 
public static void Queue1Thread(object state)
{
  while (_Exit == false)
  {
    while (_Queue1.Count > 0)
    {
      //对queue1中的数据进行处理,处理后放到queue2中 
      _Queue2.Add(_Queue1[0]);
      _Queue1.RemoveAt(0);
      Application.DoEvents();
      ShowState();
    }
  }
} 

//对queue2中的数据进行处理,处理后放到queue3中 
public static void Queue2Thread(object state)
{
  while (_Exit == false)
  {
    while (_Queue2.Count > 0)
    {
      //对queue1中的数据进行处理,处理后放到queue2中 
      _Queue3.Add(_Queue2[0]);
      _Queue2.RemoveAt(0);
      Application.DoEvents();
      ShowState();
    }
  }
}

状态监控与停止机制

为了确保UI能够反映当前的处理进度,且用户可随时停止程序,代码实现了以下辅助功能:

动态展示队列状态

ShowState 方法构建了一个描述三个队列当前数量的字符串。为了防止跨线程访问UI控件导致异常,它检查了窗体对象是否存在,若存在则通过 _OwnerForm.Invoke 将更新动作封送回UI线程执行。

//用于監視各隊列狀態的線程 
public static void ShowState()
{
  string stateInfo = 
  QueueTester._Queue1.Count.ToString() " -> " +
  QueueTester._Queue2.Count.ToString() " -> " +
  QueueTester._Queue3.Count.ToString();
  try
  {
    if (_OwnerForm != null)
    {
      _OwnerForm.Invoke(_StateMethod, stateInfo);
      Application.DoEvents();
    }
  }
  catch { /* 捕获可能的线程相关异常 */ }
}

安全停止线程

当需要中断测试时,调用 StopThread。它将 _Exit 设为 true,这会触发上述所有 while 循环的条件判断失效,从而使各个线程平滑退出。

public static void StopThread()
{
  _Exit = true; // 通知所有循环终止
  _OwnerForm = null;
}

总结

以上示例通过手动管理静态队列和使用线程池,简单演示了在C#中进行多线程多队列数据流转的基本流程。虽然该方案在原理上可行,但需要注意以下几点优化方向:
1. 锁的安全性: 当前代码未使用 lock 语句保护 IList 的读写,在高并发下可能引发冲突,建议引入同步锁或使用 ConcurrentQueue<T>。
2. 内存泄漏风险: 大量频繁地生成和丢弃随机数可能导致GC压力增大。
3. 性能考量: ArrayList 属于非泛型集合,存在装箱/拆箱开销;RemoveAt(0) 具有线性时间复杂度,若队列极长会严重拖慢处理速度。

以上就是C#多线程处理多个队列数据的详细内容,更多关于C#多线程并发编程的资料请关注本站其它相关文章!
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表