呵呵哒( ̄▽ ̄)" 2024-02-02 20:31 采纳率: 66.7%
浏览 5
已结题

异步编程C/C++不知道改得对不对

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
 
// A的实现,一般会隐藏
typedef void (*CallbackPtr)(int);// 函数指针定义
 
typedef struct dataCB{
    int data;
    CallbackPtr callback;
}dataCB;
 
 
// 创建实例
dataCB dataCBInstance = {0, NULL};
 
void* callback_thread(void* arg) { // 此处用的是一个线程
    // 循环改变p->a的值为 0 1 2 3 4 5 6 7 8 9,每个3s改变一次
    dataCB* p = (dataCB*)arg;
    while (1) {
        sleep(3);// 延时3s执行callback函数
        p->callback(p->data);// 函数指针执行函数,这个函数来自于应用层B
        p->data = (p->data + 1) % 10;
    }
}
 
void startup_app_A() {
    // 创建线程
    pthread_t tid;
    pthread_create(&tid, NULL, callback_thread, (void*)&dataCBInstance);   
}
 
// 给B的接口,接收注册函数
extern void SetCallBackFun(CallbackPtr cb) {
    printf("SetCallBackFun print! \n");
    dataCBInstance.callback = cb;
}
 
// //-----------------------应用者B-------------------------------
void recieve(int data)       // 应用者增加的函数,此函数会在A中被执行
{
    //do something
    printf("B得到A的数据 = %d\n",data);
}
 
 
int main(void) {
    // 启动A
    startup_app_A();
    SetCallBackFun(recieve);
    // 主函数
    while (1) {
        // std::cout << "main function" << std::endl;
        printf("main function\n");
        sleep(2);
    }
    return 0;
}

#include <iostream>
#include <functional>
#include <thread>
#include <unistd.h>
using namespace std;

// A的实现,一般会隐藏
using CallbackPtr = std::function<void(int)>;

typedef struct dataCB{
    int data;
    CallbackPtr callback;
}dataCB;


// 创建实例
dataCB dataCBInstance = {0, NULL};

void* callback_thread(void* arg) { // 此处用的是一个线程
    // 循环改变p->a的值为 0 1 2 3 4 5 6 7 8 9,每个3s改变一次
    dataCB* p = (dataCB*)arg;
    while (1) {
        sleep(3);// 延时3s执行callback函数
        p->callback(p->data);// 函数指针执行函数,这个函数来自于应用层B
        p->data = (p->data + 1) % 10;
    }
}

void startup_app_A() {
    // 创建线程
    std::thread(callback_thread, (void*)&dataCBInstance).detach(); // .detach()分离线程
}

// 给B的接口,接收注册函数
extern void SetCallBackFun(CallbackPtr cb) {
    printf("SetCallBackFun print! \n");
    dataCBInstance.callback = cb;
}

// //-----------------------应用者B-------------------------------
void recieve(int data)       // 应用者增加的函数,此函数会在A中被执行
{
    //do something
    printf("B得到A的数据 = %d\n",data);
}


int main(void) {
    // 启动A
    startup_app_A();
    SetCallBackFun(recieve);
    // 主函数
    while (1) {
        printf("main function\n");
        sleep(2);
    }
    return 0;
}

实现效果:

PS D:\Work\c++> ./bin/app
SetCallBackFun print! 
main function
main function
B得到A的数据 = 0
main function
main function
B得到A的数据 = 1
main function
B得到A的数据 = 2
main function
main function
B得到A的数据 = 3
main function
B得到A的数据 = 4
main function
main function
B得到A的数据 = 5
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8
main function
B得到A的数据 = 9
main function
PS D:\Work\c++> cmake --build build
[100%] Built target app
PS D:\Work\c++> ./bin/app
SetCallBackFun print! 
main function
main function
B得到A的数据 = 0
main function
B得到A的数据 = 1
main function
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
main function
B得到A的数据 = 5
main function
B得到A的数据 = 6
main function
main function
B得到A的数据 = 7
main function
B得到A的数据 = 8
main function
main function
B得到A的数据 = 9
main function
B得到A的数据 = 0
main function
main function
B得到A的数据 = 1
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
B得到A的数据 = 5
main function
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8
main function
B得到A的数据 = 9
main function
main function
B得到A的数据 = 0
main function
B得到A的数据 = 1
main function
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
B得到A的数据 = 5
main function
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8
main function
B得到A的数据 = 9
main function
main function
B得到A的数据 = 0
main function
B得到A的数据 = 1
main function
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
B得到A的数据 = 5
main function
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8
main function
B得到A的数据 = 9
main function
main function
B得到A的数据 = 0
main function
B得到A的数据 = 1
main function
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
B得到A的数据 = 5
main function
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8
main function
B得到A的数据 = 9
main function
main function
B得到A的数据 = 0
main function
B得到A的数据 = 1
main function
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
B得到A的数据 = 5
main function
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8

C++版本是我根据别人的文章C语言版本略改了一点,发现没有加.detach(分离线程)不能跑,但是加了有效果,我也不太明白这是不是异步?┭┮﹏┭┮

  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-02-02 20:32
    关注

    引自免费微信小程序:皆我百晓生

    您展示的C++代码片段实现了一个简单的异步编程模型,其中callback_thread函数在一个独立线程中运行,每3秒通过回调函数更新并发送一个数据给应用层B。在原始C语言版本的基础上,您将pthread线程API替换为了C++11标准库中的std::thread,并使用了std::function<void(int)>来代替原始的函数指针。

    关于.detach()方法,它是std::thread的一个成员函数,用于分离线程,这意味着主线程不再等待这个子线程结束就继续执行(即非阻塞)。如果不调用.detach(),当主线程结束时,若子线程还在运行,程序会因为没有join子线程而抛出异常或导致未定义行为。因此,在您的场景中,调用.detach()是必要的,这样callback_thread可以作为一个后台任务持续运行,同时主线程可以继续执行其自身的循环逻辑。

    以下是对异步编程的理解以及您代码中关键点的解释:

    1. 异步编程:异步编程的核心思想是允许任务在不阻塞主线程的情况下独立完成工作。在这个例子中,callback_thread在线程创建后立即开始执行,并在后台每隔3秒触发一次回调函数,这正是异步编程的应用场景。

    2. 线程分离:.detach()的作用就是让主线程与新创建的线程解耦,新线程成为一个守护线程,即使主线程结束,它也能继续存在并执行任务。

    3. 回调机制:您使用了std::function<void(int)>作为回调类型,它可以存储任何可调用对象(包括普通函数、lambda表达式和类的成员函数等),增强了灵活性。SetCallBackFun接收这样的回调函数,并在适当的时候通过dataCBInstance.callback调用。

    4. 整体流程:启动程序后,首先初始化A并启动callback_thread线程,然后设置回调函数为recieve。之后主线程进入无限循环打印"main function",同时callback_thread也在后台不断更新数据并触发回调,将数据传递给B端进行处理。

    所以,您的C++代码片段确实实现了异步编程,通过分离线程确保了主程序不受后台任务影响,同时利用回调机制实现了模块间的通信。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 2月11日
  • 已采纳回答 2月3日
  • 创建了问题 2月2日