『7x24小时有问必答』
  
想了解 C# 中AutoResetEvent类的详细使用方法,以及它在工控(工业控制)领域的具体应用场景,本文从基础概念、使用方法到实际工控场景,一步步为你讲解清楚。

一、AutoResetEvent 核心概念

AutoResetEvent  是 C# 中用于线程同步的核心类(位于System.Threading命名空间),作用是让一个线程等待另一个线程发出 “信号” 后再继续执行。

核心特性:

•  自动重置:当一个等待的线程获得信号并继续执行后,AutoResetEvent  会自动回到无信号状态(相当于 “一次性开关”)。
•  两种状态
• 无信号(非终止):调用WaitOne()的线程会阻塞,等待信号。
• 有信号(终止):调用WaitOne()的线程会立即继续执行,且状态自动重置为无信号。

构造函数:

1
2

// initialState: 初始状态(true=有信号,false=无信号)

AutoResetEvent autoResetEvent =  new  AutoResetEvent(bool  initialState);

核心方法:

方法
作用
WaitOne()
阻塞当前线程,直到收到信号(无超时)
WaitOne(int millisecondsTimeout)
阻塞线程,超时后自动返回 false
Set()
发送信号,唤醒一个等待的线程(自动重置)
Reset()
手动将状态重置为无信号
Dispose()
释放资源(使用完必须释放)

二、AutoResetEvent 基础使用示例

先通过一个简单示例理解核心逻辑:模拟 “生产 - 消费” 场景,生产线程生产数据后发信号,消费线程等待信号后处理数据。

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

using  System;

using  System.Threading;

class  AutoResetEventDemo

{

      // 初始化为无信号状态(消费线程先等待)

      private  static  AutoResetEvent _autoResetEvent =  new  AutoResetEvent(false);

      private  static  int  _data =  0;  // 模拟工控中的采集数据

       static  void  Main(string[]  args)

      {

            // 启动消费线程(先阻塞,等待信号)

            Thread consumerThread =  new  Thread(ConsumeData);

            consumerThread.Name =  "消费线程";

            consumerThread.Start();

            // 主线程作为生产线程,模拟每隔1秒采集一次数据

            for  (int  i =  1; i <=  5; i++)

            {

                  Thread.Sleep(1000);  // 模拟采集耗时

                  _data = i *  10;  // 模拟采集到的工控数据(如温度、压力)

                  Console.WriteLine($"[{DateTime.Now}] 生产数据:{_data},发送信号");

                  _autoResetEvent.Set();  // 发送信号,唤醒消费线程

            }

            // 等待消费线程处理完最后一次数据

            Thread.Sleep(1500);

            _autoResetEvent.Dispose();  // 释放资源

            Console.WriteLine("程序结束");

      }

      // 消费线程:处理工控数据

       private  static  void  ConsumeData()

      {

            while  (true)

            {

                  // 阻塞等待信号,超时时间设为2秒(避免无限等待)

                  bool  isSignaled = _autoResetEvent.WaitOne(2000);

                  if  (isSignaled)

                  {

                        // 收到信号,处理数据

                        Console.WriteLine($"[{DateTime.Now}]  {Thread.CurrentThread.Name}  处理数据:{_data}");

                  }

                  else

                  {

                        // 超时,退出循环

                        Console.WriteLine($"[{DateTime.Now}]  {Thread.CurrentThread.Name}  超时,无新数据,退出");

                        break;

                  }

            }

      }

}

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12

[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. 工控使用时需重点关注超时容错、非阻塞检查、资源释放,确保系统稳定可靠。
  

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

上一主题上一主题         下一主题下一主题
QQ手机版小黑屋粤ICP备17165530号

关于我们·投诉举报· 用户帮助· 联系我们 · 本站服务 · 版权声明· 隐私政策 · 投搞指南

法律保护:PLC技术网,plcjs.com,plcjs.net等字样
Copyright 2010-2030. All rights reserved. 


微信公众号二维码 抖音二维码 百家号二维码 今日头条二维码哔哩哔哩二维码