C#在工业自动化上位机中,如何使用观察者和消费者模式
一、先明确两个模式在上位机里的作用
1. 观察者模式(Observer)
用途:数据变化时,自动通知 UI、报警、日志、曲线等多个模块更新。
典型场景:
- PLC 数据刷新 → 界面显示
- 温度超标 → 触发报警
- 数据变化 → 写入日志
- 数据变化 → 曲线控件更新
一句话:一个数据源变了,N 个地方自动跟着变。
2. 生产者 - 消费者模式(Producer-Consumer)
用途:解耦 “数据采集” 和 “数据处理”,防止界面卡顿、数据丢失、线程爆炸。
典型场景:
- PLC 高频采集(10ms 一次)
- 数据解析、入库、日志写入慢
- 不能阻塞采集线程
- 不能丢包
一句话:生产只管扔数据,消费只管慢慢处理,互不干扰。
二、场景设定(真实上位机)
假设我们做一个温控设备上位机:
- 定时从 Modbus/TCP 或 PLC 读取温度、压力
- 数据到达后:
- 更新主界面显示
- 判断是否报警
- 写入日志
- 存入数据库
- 采集高频(100ms),处理较慢,必须用生产者 - 消费者
- 数据变化要通知多个模块 → 观察者模式
三、第一步:定义数据实体(DeviceData)
1 // 设备数据 2 public class DeviceData 3 { 4 // 温度 5 public double Temperature { get; set; } 6 // 压力 7 public double Pressure { get; set; } 8 // 采集时间 9 public DateTime CollectTime { get; set; } 10 }
四、观察者模式实现(数据主题 + 多个观察者)
1. 抽象观察者接口
1 public interface IDataObserver 2 { 3 // 数据更新时被调用 4 void OnDataUpdate(DeviceData data); 5 }
2. 主题(被观察者:数据中心)
1 public class DataSubject 2 { 3 // 保存所有观察者 4 private readonly List<IDataObserver> _observers = new List<IDataObserver>(); 5 6 // 注册观察者 7 public void Attach(IDataObserver observer) 8 { 9 _observers.Add(observer); 10 } 11 12 // 移除观察者 13 public void Detach(IDataObserver observer) 14 { 15 _observers.Remove(observer); 16 } 17 18 // 通知所有观察者 19 public void Notify(DeviceData data) 20 { 21 foreach (var observer in _observers) 22 { 23 observer.OnDataUpdate(data); 24 } 25 } 26 }
3. 具体观察者 A:UI 界面更新
1 public class UiDisplayObserver : IDataObserver 2 { 3 public void OnDataUpdate(DeviceData data) 4 { 5 // 真实项目中使用 Dispatcher 切换到 UI 线程 6 Application.Current.Dispatcher.Invoke(() => 7 { 8 Console.WriteLine($"【UI更新】温度:{data.Temperature} ℃"); 9 }); 10 } 11 }
4. 具体观察者 B:报警监测
1 public class AlarmObserver : IDataObserver 2 { 3 public void OnDataUpdate(DeviceData data) 4 { 5 if (data.Temperature > 60) 6 { 7 Console.WriteLine($"【报警】温度过高!当前:{data.Temperature}"); 8 } 9 } 10 }
5. 具体观察者 C:日志记录
1 public class LogObserver : IDataObserver 2 { 3 public void OnDataUpdate(DeviceData data) 4 { 5 Console.WriteLine($"【日志】{data.CollectTime} T={data.Temperature} P={data.Pressure}"); 6 } 7 }
五、生产者 - 消费者模式(处理高频采集)
工业上位机必须用这个,否则高频采集会卡死 UI。
这里用
BlockingCollection<T>(线程安全队列)。1 using System.Collections.Concurrent; 2 3 public class DataQueue 4 { 5 // 阻塞队列,线程安全 6 private readonly BlockingCollection<DeviceData> _queue = new BlockingCollection<DeviceData>(); 7 8 // 生产者:扔数据进入队列 9 public void Produce(DeviceData data) 10 { 11 _queue.Add(data); 12 } 13 14 // 消费者:后台持续处理 15 public void StartConsume(DataSubject subject) 16 { 17 Task.Run(() => 18 { 19 while (!_queue.IsCompleted) 20 { 21 // 没有数据会自动阻塞,不占CPU 22 if (_queue.TryTake(out var data, -1)) 23 { 24 // 数据解析完成 → 通知所有观察者 25 subject.Notify(data); 26 } 27 } 28 }); 29 } 30 }
六、模拟 PLC 数据采集(生产者)
1 public class PlcCollector 2 { 3 private readonly DataQueue _dataQueue; 4 private Timer _timer; 5 6 public PlcCollector(DataQueue queue) 7 { 8 _dataQueue = queue; 9 } 10 11 // 开始采集 12 public void StartCollect() 13 { 14 // 100ms 采集一次(模拟高频) 15 _timer = new Timer(CollectCallback, null, 0, 100); 16 } 17 18 private void CollectCallback(object state) 19 { 20 // 模拟从 PLC 读取数据 21 var data = new DeviceData 22 { 23 Temperature = new Random().Next(40, 80), 24 Pressure = new Random().Next(100, 200), 25 CollectTime = DateTime.Now 26 }; 27 28 // 扔给队列,不做任何处理 29 _dataQueue.Produce(data); 30 } 31 }
七、上位机主程序入口(组装整个系统)
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 // 1. 创建主题 6 var subject = new DataSubject(); 7 8 // 2. 注册观察者 9 subject.Attach(new UiDisplayObserver()); 10 subject.Attach(new AlarmObserver()); 11 subject.Attach(new LogObserver()); 12 13 // 3. 创建队列 14 var dataQueue = new DataQueue(); 15 16 // 4. 启动消费者 17 dataQueue.StartConsume(subject); 18 19 // 5. 启动 PLC 采集(生产者) 20 var collector = new PlcCollector(dataQueue); 21 collector.StartCollect(); 22 23 Console.ReadLine(); 24 } 25 }
八、运行结果(典型工业上位机逻辑)
1 【UI更新】温度:58 ℃ 2 【日志】2025-08-23 15:30:20 T=58 P=122 3 【UI更新】温度:65 ℃ 4 【报警】温度过高!当前:65 5 【日志】2025-08-23 15:30:21 T=65 P=145
九、为什么工业上位机必须这么写?(核心价值)
1. 观察者模式好处
- 采集线程只负责采集,不关心谁要显示、谁要报警
- 新增功能(如曲线、数据库)不用改采集代码
- 低耦合、易扩展、符合上位机软件架构规范
2. 生产者 - 消费者好处
- 采集 100ms 极快,处理再慢也不阻塞采集
- 不会丢数据
- 不会开一堆线程导致系统崩溃
- 界面永远不卡顿
3. 架构优势
- 采集层 ↔ 队列 ↔ 解析层 ↔ 业务层 ↔ UI
完全分层,标准工业软件架构。
十、对应 WPF 上位机怎么改?
只需要把观察者中的:
1 Application.Current.Dispatcher.Invoke(() => { 2 // 更新绑定的 ViewModel 属性 3 vm.Temp = data.Temperature; 4 });
即可实现MVVM + 观察者 + 生产消费的标准工业上位机架构。
十一、一句话总结
- 观察者模式 = 数据一变,多处自动更新(UI / 报警 / 日志)
- 生产者 - 消费者 = 采集与处理分离,保证高速稳定不卡顿
这是几乎所有 C# 工业自动化上位机的标准底层架构。
浙公网安备 33010602011771号