使用 C# 实现一个设备指令队列管理器

在开发硬件设备相关的软件时,例如:

工业控制设备

智能硬件

机器人设备

测试仪器

IoT 设备

上位机通常需要向设备发送各种控制指令。

例如:

开启设备

设置参数

获取状态

执行校准

固件升级

但是在实际通信过程中,并不是所有指令都可以立即发送。

很多设备通信协议都有类似限制:

同一时间只能执行一条指令

上一条指令需要等待设备返回结果

指令需要按照顺序执行

某些指令需要超时重试

如果直接在业务代码中处理这些逻辑,代码很容易变得混乱。

因此,可以设计一个简单的设备指令队列管理器(Command Queue Manager),统一管理设备指令发送流程。

本文将使用 C# 实现一个简单版本的设备指令队列管理器。

一、为什么需要指令队列

假设现在有一个设备,需要执行以下操作:

1. 设置设备参数

2. 启动设备

3. 获取运行状态

4. 停止设备

最简单的写法可能是:

SendCommand("SET_PARAM");

SendCommand("START");

SendCommand("GET_STATUS");

SendCommand("STOP");

但是设备实际处理速度可能没有这么快。

例如:

发送 SET_PARAM

等待设备响应

收到 OK

发送 START

等待设备响应

如果程序连续发送:

SET_PARAM

START

GET_STATUS

STOP

设备可能无法正确处理。

因此需要一个中间管理层:

业务层

  ↓

指令队列

  ↓

通信模块

  ↓

硬件设备

业务层只负责添加指令。

队列负责控制发送顺序。

二、设计一个简单的指令模型

首先定义一个设备指令对象。

public class DeviceCommand

{

    public string Name { get; set; }

    public byte[] Data { get; set; }

    public int Timeout { get; set; }

    public Action<bool> Callback { get; set; }

}

其中:

Name:

表示指令名称。

例如:

START_DEVICE

Data:

表示实际发送的数据。

例如:

AA 01 00 FF

Timeout:

表示等待设备响应时间。

Callback:

用于通知执行结果。

例如:

command.Callback(true);

表示执行成功。

三、实现指令队列管理器

创建一个管理类:

public class DeviceCommandQueue

{

    private Queue<DeviceCommand> commandQueue

        = new Queue<DeviceCommand>();

    private bool isExecuting = false;

}

其中:

Queue 用于保存等待执行的指令。

isExecuting:

表示当前是否正在执行。

避免多个指令同时发送。

添加指令方法:

public void AddCommand(DeviceCommand command)

{

    commandQueue.Enqueue(command);

    ExecuteNext();

}

当添加新指令后:

自动尝试执行下一条。

四、实现指令顺序执行

核心逻辑:

private async void ExecuteNext()

{

    if(isExecuting)

        return;

    if(commandQueue.Count == 0)

        return;

    isExecuting = true;

    DeviceCommand command = commandQueue.Dequeue();

    Console.WriteLine(

        "发送指令:" + command.Name);

    bool result = await SendCommand(command);

    command.Callback?.Invoke(result);

    isExecuting = false;

    ExecuteNext();

}

执行流程:

取出第一条指令

发送设备

等待结果

回调通知

执行下一条

这样可以保证:

任何时候只有一个指令正在执行。

五、模拟设备通信过程

实际项目中:

SendCommand 通常会连接:

串口

TCP

蓝牙

USB

这里简单模拟。

private async Task<bool> SendCommand(

    DeviceCommand command)

{

    Console.WriteLine(

        "发送数据");

    await Task.Delay(1000);

    Console.WriteLine(

        "设备返回成功");

    return true;

}

调用:

var queue = new DeviceCommandQueue();

queue.AddCommand(

    new DeviceCommand

    {

        Name = "启动设备",

        Data = new byte[]

        {

            0xAA,

            0x01

        },

        Callback = result =>

        {

            Console.WriteLine(

            "执行结果:" + result);

        }

    });

queue.AddCommand(

    new DeviceCommand

    {

        Name = "读取状态"

    });

执行结果:

发送指令:启动设备

等待设备响应

设备返回成功

执行结果:true

发送指令:读取状态

等待设备响应

设备返回成功

六、实际项目中可以继续扩展的方向

上面的实现只是一个基础版本。

在真实设备项目中,通常还会增加更多功能。

1. 指令超时处理

例如:

设备 3 秒没有响应。

自动失败:

Task.Delay(timeout)

超过时间:

Command Timeout

然后执行下一条。

2. 指令重试机制

例如:

WiFi 通信不稳定。

第一次失败:

发送失败

重新发送

最多3次

可以增加:

RetryCount

字段。

3. 优先级队列

有些指令优先级更高。

例如:

紧急停止:

STOP

应该优先于:

读取数据

可以将 Queue 改为 PriorityQueue。

4. 指令状态管理

例如:

Waiting

Sending

Success

Failed

方便日志记录和问题排查。

对于上位机开发来说,一个稳定的指令队列管理器是比较常见的基础模块。

无论是串口设备、网络设备,还是工业控制设备,只要涉及“发送指令 → 等待响应 → 继续执行”的通信模式,都可以使用类似的设计方式。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容