C++编程——异步处理、事件驱动编程和策略模式

发布于:2025-09-06 ⋅ 阅读:(16) ⋅ 点赞:(0)

异步处理、事件驱动编程、和 策略模式


一、异步处理(Asynchronous Processing)

定义:

异步处理是一种编程模型,允许任务在等待耗时操作(如 I/O、网络请求)完成的同时,不阻塞其他任务的执行。

类比场景:

排队点奶茶 vs 自助取号叫号系统

  • 同步处理: 你在柜台排队点奶茶,等前面的人点完才轮到你。
  • 异步处理: 你在门口的机器上取个号,然后在旁边玩手机,等叫到你再上前点单。

你不必等前面所有人点完才能做别的事(=不会阻塞主线程)。

代码示例(C++ 伪代码):

#include <future>
#include <iostream>

int longTask() {
    std::this_thread::sleep_for(std::chrono::seconds(3));
    return 42;
}

int main() {
    std::future<int> result = std::async(std::launch::async, longTask);

    std::cout << "任务开始,我先去做别的事情...\n";

    // 等待 longTask 完成
    int value = result.get();
    std::cout << "任务结果:" << value << std::endl;
    return 0;
}

二、事件驱动编程(Event-Driven Programming)

定义:

事件驱动是一种编程范式,程序的流程由事件(Event)触发来控制。每当某个事件发生,就调用对应的“事件处理器”。

类比场景:

门铃系统

  • 门口安装了一个门铃(event)。
  • 有人按门铃(事件发生),系统立刻响铃或通知你(事件处理器)。
  • 没人按门铃时,你可以自由做别的事。

你不需要时刻去检测门口是否有人,而是等事件触发你再响应。

代码示例(JavaScript 常见):

document.getElementById("myButton").addEventListener("click", function() {
    alert("按钮被点击了!");
});

你设置一个事件监听器(Event Listener),当“点击事件”发生时执行某段代码。

C++ 中可以通过回调函数、观察者模式等方式实现类似的事件驱动效果。


三、策略模式(Strategy Pattern)

定义:

策略模式是一种行为设计模式,定义一系列算法,把它们封装起来,并且使它们可以相互替换。客户端不关心具体策略细节,只关注调用统一接口

类比场景:

导航路线选择

  • 你要开车去目的地,可以选择:最快路线最短路线避开收费
  • 不同的策略(开车方式)可以随时切换,但你都只管告诉系统“带我去”。

系统内部选择使用哪个策略,用户无感。

C++ 示例代码:

// 策略接口
class TravelStrategy {
public:
    virtual void travel() = 0;
};

// 具体策略1
class CarStrategy : public TravelStrategy {
public:
    void travel() override {
        std::cout << "开车去旅行\n";
    }
};

// 具体策略2
class TrainStrategy : public TravelStrategy {
public:
    void travel() override {
        std::cout << "坐火车去旅行\n";
    }
};

// 上下文(使用策略的环境)
class TravelContext {
private:
    TravelStrategy* strategy;
public:
    void setStrategy(TravelStrategy* s) {
        strategy = s;
    }

    void go() {
        strategy->travel();
    }
};

// 使用
int main() {
    TravelContext ctx;
    CarStrategy car;
    TrainStrategy train;

    ctx.setStrategy(&car);
    ctx.go(); // 输出:开车去旅行

    ctx.setStrategy(&train);
    ctx.go(); // 输出:坐火车去旅行

    return 0;
}

总结对比表:

名称 核心思想 类比场景 应用场景
异步处理 不阻塞当前线程,等待操作完成 奶茶取号系统 网络通信、文件IO
事件驱动编程 响应事件触发,执行特定操作 按门铃触发动作 UI开发、网络服务器
策略模式 行为封装,可随时替换使用方式 不同路线导航选择 可切换的算法或行为(如排序)

异步处理、事件驱动编程和策略模式 在嵌入式 C++ 中的运用

一、异步处理在嵌入式 C++ 中的运用

定义与场景

嵌入式系统中常需要处理耗时的操作,例如:

  • 串口、以太网通信
  • 传感器数据采集
  • SD 卡或 NAND Flash 读写
  • OTA 升级等文件传输

这些操作如果同步执行,会阻塞主线程,影响系统的实时性与响应能力。

运用方式

  1. 使用 RTOS 中的任务调度或消息队列
  2. 使用中断回调函数 + 状态机机制
  3. 引入异步 I/O 框架(如 Boost.Asio)统一管理异步操作

示例:异步读取串口数据

void uart_read_callback(uint8_t* data, size_t len) {
    // 处理接收到的数据
}

void poll_uart() {
    if (uart_data_available()) {
        uint8_t buffer[64];
        size_t len = uart_read(buffer, sizeof(buffer));
        uart_read_callback(buffer, len);
    }
}

二、事件驱动编程在嵌入式 C++ 中的运用

定义与场景

事件驱动是一种通过事件(如中断、输入)来控制流程的编程方式。常见事件包括:

  • 按键按下
  • 定时器中断
  • 外设数据到达(UART、SPI)
  • 网络事件(连接、断开)

运用方式

  1. 利用中断服务程序设置事件标志或往事件队列投递消息
  2. 在主循环中轮询事件队列并执行对应处理器
  3. 使用状态机结合事件系统

示例:事件驱动模型伪代码

enum EventType {
    EVENT_BUTTON_PRESS,
    EVENT_UART_RX,
    ...
};

struct Event {
    EventType type;
    void* data;
};

std::queue<Event> event_queue;

void isr_button_press() {
    event_queue.push({EVENT_BUTTON_PRESS, nullptr});
}

void event_loop() {
    while (true) {
        if (!event_queue.empty()) {
            Event evt = event_queue.front();
            event_queue.pop();

            switch (evt.type) {
                case EVENT_BUTTON_PRESS:
                    handle_button();
                    break;
                case EVENT_UART_RX:
                    handle_uart(evt.data);
                    break;
            }
        }
    }
}

三、策略模式在嵌入式 C++ 中的运用

定义与场景

策略模式用于在运行时动态选择行为实现,是一种面向对象的解耦方式。嵌入式中可用于以下场景:

  • 选择不同通信方式(如 SPI、UART、I2C)
  • 切换加密算法或数据编码方式
  • 控制日志输出行为(输出到串口或文件)

运用方式

  1. 抽象接口定义行为
  2. 多个具体类分别实现该行为
  3. 通过 setStrategy() 等接口注入行为

示例:发送策略(UART / SPI)

class SendStrategy {
public:
    virtual void send(const uint8_t* data, size_t len) = 0;
};

class UartSend : public SendStrategy {
public:
    void send(const uint8_t* data, size_t len) override {
        uart_send(data, len);
    }
};

class SpiSend : public SendStrategy {
public:
    void send(const uint8_t* data, size_t len) override {
        spi_send(data, len);
    }
};

class Device {
    SendStrategy* strategy;
public:
    void setStrategy(SendStrategy* s) { strategy = s; }
    void transmit(const uint8_t* data, size_t len) {
        strategy->send(data, len);
    }
};

四、Boost.Asio 在嵌入式 C++ 中的详细说明

简介

Boost.Asio 是一个跨平台的异步 I/O 库,提供统一接口处理异步串口、定时器、网络通信等。其主要优点是抽象统一、无需依赖多线程即可实现非阻塞操作。

核心概念

组件 描述
io_context 核心事件循环调度器
serial_port 串口抽象对象,封装串口操作
steady_timer 定时器,用于定时异步回调
async_* 函数 执行异步任务,如 async_read, async_write
handler 异步完成后的回调
strand 保证回调序列化执行

示例:串口异步接收

#include <boost/asio.hpp>
#include <iostream>

using namespace boost;

asio::io_context io;
asio::serial_port serial(io, "/dev/ttyUSB0");

char read_buf[256];

void read_handler(const system::error_code& ec, std::size_t bytes_transferred) {
    if (!ec) {
        std::cout << "Received: " << std::string(read_buf, bytes_transferred) << std::endl;
        serial.async_read_some(asio::buffer(read_buf), read_handler); // 再次接收
    }
}

int main() {
    serial.set_option(asio::serial_port_base::baud_rate(9600));
    serial.async_read_some(asio::buffer(read_buf), read_handler);
    io.run(); // 启动事件循环
    return 0;
}

在嵌入式环境中使用建议

项目 建议说明
资源优化 关闭异常处理(-fno-exceptions
平台适配 可交叉编译至 ARM Cortex-M / Linux
可裁剪性 移除 TCP/UDP 支持,仅保留串口和定时器模块
替代方案 libuv、libevent、或裸写异步驱动

总结

项目/模式 嵌入式中作用 示例场景
异步处理 非阻塞等待,提高系统响应 串口、文件IO、OTA
事件驱动编程 精准控制流程、节省资源 中断处理、外设事件
策略模式 支持行为切换、增加灵活性 通信方式切换、算法选择
Boost.Asio 跨平台高效异步库,简化异步操作 异步串口、定时器、轻量网络服务

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到