ConcurrentQueue并发队列和SemaphoreSlim轻量级信号量

ConcurrentQueue 并发队列
 
SemaphoreSlim 轻量级信号量
 
这两个是做 生产者 - 消费者、高频数据采集、多线程采集不卡顿 的核心工具,也是工控上位机必用知识点。

一、ConcurrentQueue 并发队列

1. 是什么?

ConcurrentQueue<T> = 线程安全的先进先出队列
 
普通 Queue<T> 不是线程安全的,多线程同时读写会直接报错或数据错乱。
 
工控场景:
  • 采集线程(生产者)不断入队
  • 处理线程(消费者)不断出队
     
    必须用 ConcurrentQueue

2. 核心特点

  • 线程安全,无需 lock
  • 无边界(默认无限长度)
  • 高性能,适合高并发
  • 先进先出 FIFO

3. 常用方法

 1 // 入队(生产者)
 2 queue.Enqueue(item);
 3 
 4 // 尝试出队(消费者)
 5 if (queue.TryDequeue(out var item))
 6 {
 7     // 处理数据
 8 }
 9 
10 // 查看队首元素,不出队
11 if (queue.TryPeek(out var item))
12 
13 // 清空队列
14 while (queue.TryDequeue(out _)) { }
15 
16 // 获取数量
17 int count = queue.Count;

4. 工业上位机典型用法

 1 // 全局并发队列
 2 private readonly ConcurrentQueue<DeviceData> _dataQueue = new();
 3 
 4 // 生产者:PLC 采集线程
 5 void CollectThread()
 6 {
 7     while (true)
 8     {
 9         var data = ReadFromPLC();  // 从 PLC 读取
10         _dataQueue.Enqueue(data);  // 入队
11         Thread.Sleep(100);
12     }
13 }
14 
15 // 消费者:数据处理线程
16 void ProcessThread()
17 {
18     while (true)
19     {
20         if (_dataQueue.TryDequeue(out var data))
21         {
22             // 更新UI、写库、报警判断
23         }
24         Thread.Sleep(10);
25     }
26 }

优点:

  • 采集不卡处理
  • 处理不拖慢采集
  • 不会丢数据
  • 不会报集合修改异常

二、SemaphoreSlim 轻量级信号量

1. 是什么?

SemaphoreSlim = 控制同时运行的线程数量
可以理解为:“限制多少个人同时进房间”
工控上位机用途:
  • 限制同时处理的任务数
  • 实现 等待 + 通知 机制
  • 解决消费者线程空转浪费 CPU
  • 生产者生产后通知消费者 “来活了”

2. 核心作用

  1. 限流(最多 N 个线程同时运行)
  2. 线程同步(生产者通知消费者)
  3. 避免消费者无限循环耗 CPU

3. 常用方法

 1 // 创建信号量,初始0,最大1000
 2 var semaphore = new SemaphoreSlim(0, 1000);
 3 
 4 // 等待信号(阻塞直到有信号)
 5 semaphore.Wait();
 6 
 7 // 异步等待(不阻塞线程,上位机常用)
 8 await semaphore.WaitAsync();
 9 
10 // 释放一个信号
11 semaphore.Release();
12 
13 // 释放多个信号
14 semaphore.Release(5);

4. 为什么上位机必须用它?

如果只用 ConcurrentQueue,消费者要这样写:
1 while (true)
2 {
3     if (queue.TryDequeue(...)) { ... }
4     Thread.Sleep(10);
5 }

问题:

  • CPU 一直空转
  • 延迟高
  • 浪费资源
使用 SemaphoreSlim 后:
  • 没数据时 线程休眠,不占 CPU
  • 有数据时 立即唤醒
  • 工业标准用法

三、终极组合:ConcurrentQueue + SemaphoreSlim

(工控上位机标准生产者 - 消费者架构)

完整示例代码

 1 // 数据实体
 2 public class DeviceData
 3 {
 4     public float Temperature { get; set; }
 5     public DateTime Time { get; set; }
 6 }
 7 
 8 public class DataProcessService
 9 {
10     // 并发队列
11     private readonly ConcurrentQueue<DeviceData> _queue = new();
12 
13     // 信号量
14     private readonly SemaphoreSlim _semaphore = new(0, int.MaxValue);
15 
16     // 运行标志
17     private bool _isRunning;
18 
19     // 启动消费者
20     public void StartConsumer()
21     {
22         _isRunning = true;
23 
24         Task.Run(async () =>
25         {
26             while (_isRunning)
27             {
28                 try
29                 {
30                     // 等待信号(没数据就休眠)
31                     await _semaphore.WaitAsync();
32 
33                     // 取出数据
34                     if (_queue.TryDequeue(out var data))
35                     {
36                         // 处理:更新UI、写库、报警
37                         ProcessData(data);
38                     }
39                 }
40                 catch (Exception ex)
41                 {
42                     // 异常处理
43                 }
44             }
45         });
46     }
47 
48     // 生产者:往队列里扔数据
49     public void AddData(DeviceData data)
50     {
51         _queue.Enqueue(data);
52         _semaphore.Release(); // 通知消费者来取
53     }
54 
55     // 模拟数据处理
56     private void ProcessData(DeviceData data)
57     {
58         Console.WriteLine($"处理温度:{data.Temperature} ℃");
59     }
60 
61     public void Stop()
62     {
63         _isRunning = false;
64     }
65 }

使用方式

 1 var service = new DataProcessService();
 2 service.StartConsumer();
 3 
 4 // 模拟 PLC 采集线程(生产者)
 5 while (true)
 6 {
 7     var data = new DeviceData
 8     {
 9         Temperature = 50 + new Random().Next(0, 20),
10         Time = DateTime.Now
11     };
12 
13     service.AddData(data);
14     Thread.Sleep(100);
15 }

四、两者配合的真正优势(工控必看)

1. ConcurrentQueue 负责

  • 线程安全存取数据
  • 保证顺序
  • 不丢包

2. SemaphoreSlim 负责

  • 没有数据时 不占用 CPU
  • 有数据时 立即唤醒处理
  • 避免死循环空转
  • 实现高效的生产消费模型

3. 最终效果

  • 采集 1ms 也不卡
  • 处理再慢也不影响采集
  • CPU 占用极低
  • 上位机界面永远流畅
  • 工业标准、稳定可靠

五、一句话总结

  • ConcurrentQueue = 线程安全队列,负责存数据
  • SemaphoreSlim = 线程通知器,负责唤醒消费者
  • 两者组合 = 工业上位机标准生产者 - 消费者模型
posted on 2026-03-27 16:00  工业搬砖猿Lee  阅读(53)  评论(0)    收藏  举报