C#串口通信之信号量使用
- 背景
我在实际工作中遇到这种情况,在给煤矿企业做智能充电架系统的时候,需要有一个周期查询函数一直轮询当前充电架中每个抽屉所有充电的状态,这个轮询是在一个后台线程中执行。
还有一些功能比如人脸识别打开充电柜的某一个抽屉的门、使用人员更换下发人员信息绑定、给某个抽屉发送错误清除指令、发送和关闭LED屏幕的信息等操作都会和周期轮询竞争资源。比如会报如下错误。
这个时候可以使用信号量进行同步处理。
-
信号量使用
Semaphore,是负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。也是操作系统中用于控制进程同步互斥的量。
Semaphore常用的方法有两个WaitOne()和Release(),Release()的作用是退出信号量并返回前一个计数,而WaitOne()则是阻止当前线程,直到当前线程的WaitHandle 收到信号。这里我举一个例子让大家更容易理解:
当我们这样实例化Semaphore时候
Semaphore sema = new Semaphore(x,y)
有一队人排队上洗手间,人就相当于线程,x为还剩余的位置数量,y为总的位置数量。
WaitOne()方法就相当于人在等待洗手间位置的行为,而Release()方法就相当于一个人从洗手间出来的行为,这里再假设x和y都为5,说明开始的时候洗手间有5个空位置,且总共只有5个位置,当一队超过5个人的队伍要上洗手间的就排队,首先WaitOne()方法等待,发现有空位就依次进去,每进去一个空位减一,直到进去5之后个没有空位,这时候后面的人就一直等待,直到进去的人从洗手间出来Release()方法,空位加一,在等待WaitOne()方法的人发现有空位又进去一个空位减一……如此循环往复。
- 示例代码
/// <summary>
/// 定义信号量
///可写的信号
/// </summary>
public static Semaphore s_WriteSerialPort;
s_WriteSerialPort = new Semaphore(1, 1);//* 限制最大同时运行值,初始值为0*/
//后台线程查询串口
var t = new Thread(() =>
{
Invoke(new Action(() =>
{
//需要监听的逻辑
LOOPChecker();
}));
//Thread.Sleep(1000);
})
{
IsBackground = true,
Name = "Name" + Guid.NewGuid().ToString("N")
};
t.Start();
//是否有数据发送串口
s_WriteSerialPort.WaitOne();
serialPortUtil.Write(senBytes, 0, 8);
Thread.Sleep(150);
// 释放信号量
s_WriteSerialPort.Release();
//人脸识别 远程开门
//是否有数据发送串口
ChargingCabinetHelper. s_WriteSerialPort.WaitOne();
//向下位机发送开们指令
ChargingCabinetHelper. RemoteUnlocking(retCommandPcirInfo);
//释放信号量
ChargingCabinetHelper.s_WriteSerialPort.Release();
其他不一一举例。