[2026/1/20 10:00:01] 生产数据:10,发送信号[2026/1/20 10:00:01] 消费线程 处理数据:10[2026/1/20 10:00:02] 生产数据:20,发送信号[2026/1/20 10:00:02] 消费线程 处理数据:20[2026/1/20 10:00:03] 生产数据:30,发送信号[2026/1/20 10:00:03] 消费线程 处理数据:30[2026/1/20 10:00:04] 生产数据:40,发送信号[2026/1/20 10:00:04] 消费线程 处理数据:40[2026/1/20 10:00:05] 生产数据:50,发送信号[2026/1/20 10:00:05] 消费线程 处理数据:50[2026/1/20 10:00:07] 消费线程 超时,无新数据,退出程序结束 关键说明:
1. _autoResetEvent 初始为false(无信号),消费线程调用WaitOne()后立即阻塞。
2. 生产线程调用Set()发送信号,消费线程被唤醒并处理数据,处理完成后AutoResetEvent自动回到无信号状态。
3. 消费线程设置超时时间,避免程序无限阻塞(工控场景中必须考虑超时,防止设备卡死)。
三、AutoResetEvent 在工控中的典型应用场景
工控系统的核心需求是实时性、同步性、可靠性,AutoResetEvent 适合处理 “事件触发式” 的线程同步场景,以下是高频应用:
场景 1:工控设备数据采集与处理分离
• 背景:工控系统中,通常一个线程负责从传感器 / PLC(如西门子 S7-1200/1500、三菱 FX 系列)采集数据(如温度、压力、电机转速),另一个线程负责数据处理 / 上传。
• 使用方式:
• 采集线程:采集到有效数据后,调用Set()发送信号。
• 处理线程:调用WaitOne()等待信号,收到后立即处理数据(如校验、换算、上传到 SCADA/MES 系统)。
• 优势:避免处理线程空循环轮询(浪费 CPU),仅在有数据时才执行,符合工控 “按需响应” 的要求。
场景 2:工控指令的异步响应等待
• 背景:向工控设备(如伺服电机、变频器)发送控制指令后,需要等待设备返回 “执行完成” 信号,再执行下一步操作。
• 使用方式: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
// 指令发送线程public void SendControlCommand(string command){ // 1. 向变频器发送启动指令 PlcClient.SendCommand(command); // 2. 等待设备返回执行完成信号(由接收线程触发) bool isCompleted = _autoResetEvent.WaitOne(5000); // 超时5秒(工控设备响应超时需容错) if (isCompleted) { Console.WriteLine("指令执行成功"); } else { Console.WriteLine("指令执行超时,触发报警"); AlarmSystem.TriggerAlarm(); // 工控场景:超时触发声光报警 }}// 设备响应接收线程private void ReceivePlcResponse(){ while (_isRunning) { var response = PlcClient.ReceiveResponse(); if (response.Status == "Completed") { _autoResetEvent.Set(); // 收到完成信号,唤醒等待线程 } }} 场景 3:工控系统的紧急停止(急停)处理
• 背景:工控系统需响应急停按钮信号,立即停止所有运行中的线程(如电机控制、物料传输)。
• 使用方式: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
private AutoResetEvent _emergencyStopEvent = new AutoResetEvent(false);// 急停按钮监听线程private void MonitorEmergencyStop(){ while (_isRunning) { // 读取急停按钮状态(模拟PLC输入点) bool isStopPressed = PlcClient.ReadInput("I0.0"); if (isStopPressed) { _emergencyStopEvent.Set(); // 发送急停信号 Console.WriteLine("触发急停,所有线程停止"); break; } Thread.Sleep(10); // 高频监听(工控场景10ms级) }}// 电机控制线程private void MotorControlThread(){ while (_isRunning) { // 先检查是否有急停信号(无信号则继续运行) if (_emergencyStopEvent.WaitOne(0)) // 非阻塞检查信号 { StopMotor(); // 立即停止电机 _isRunning = false; break; } // 正常控制电机转速 MotorController.SetSpeed(1000); Thread.Sleep(50); }} • 关键:WaitOne(0) 表示非阻塞检查,线程无需阻塞,仅在急停信号触发时立即响应,保证工控系统的实时性。
四、工控场景使用注意事项
1. 超时设置必须合理:工控设备响应速度有限(如 PLC 响应 100ms~1s),需根据设备特性设置WaitOne超时时间,且超时后必须触发报警 / 容错逻辑(避免系统卡死)。
2. 避免多线程竞争:AutoResetEvent 每次Set()仅唤醒一个等待线程,若多个线程等待,需使用ManualResetEvent(手动重置),或为每个线程分配独立的AutoResetEvent。
3. 资源释放:工控系统通常 7x24 小时运行,使用完AutoResetEvent后必须调用Dispose()释放资源,避免内存泄漏。
4. 信号丢失处理:工控场景中若Set()在WaitOne()之前调用,信号会丢失(AutoResetEvent无信号队列),需通过状态变量辅助(如_isDataReady)。
总结
1. AutoResetEvent 是 C# 中自动重置的线程同步工具,核心是Set()发信号、WaitOne()等信号,信号触发后自动重置为无信号状态。
2. 工控场景中,它主要用于数据采集与处理同步、设备指令响应等待、急停信号触发等实时性要求高的线程同步场景。
3. 工控使用时需重点关注超时容错、非阻塞检查、资源释放,确保系统稳定可靠。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!