You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻塞程序执行直至回调函数完成运行?

解决异步回调未完成时main函数提前退出的问题

这是个很常见的异步操作同步等待场景,咱们可以用C++标准库的同步原语来实现阻塞,直到回调函数执行完成。下面给你两种实用的解决方案:

方案一:使用std::condition_variable + std::mutex(推荐,适合重复调用场景)

这种方式需要给InterfaceColliseo类添加几个同步成员变量,用来跟踪回调是否完成,并通知主线程等待。

第一步:修改InterfaceColliseo类定义

在类的头文件里添加同步相关的成员:

#include <mutex>
#include <condition_variable>

class InterfaceColliseo {
    // 保留你原有的成员和方法...
private:
    std::mutex m_callbackMutex;
    std::condition_variable m_callbackCondVar;
    bool m_callbackCompleted = false;

public:
    // 新增方法:阻塞直到回调完成
    void waitUntilCallbackDone() {
        std::unique_lock<std::mutex> lock(m_callbackMutex);
        // 等待回调完成的标志变为true,避免虚假唤醒
        m_callbackCondVar.wait(lock, [this](){ return m_callbackCompleted; });
        // 重置标志,方便后续重复调用getImage
        m_callbackCompleted = false;
    }

    // 修改原有的dataReceived回调方法
    void dataReceived(std::shared_ptr<IData> data) {
        // 保留你原有的业务逻辑...
        if (!data->isValid()) return;
        const unsigned char* twoDImageData = data->get2DImageData();
        int width2DImageData = data->getWidth2DImageData();
        int height2DImageData = data->getHeight2DImageData();
        const unsigned char* disparityData = data->getDisparityData();
        int widthDisparityData = data->getWidthDisparityData();
        int heightDisparityData = data->getHeightDisparityData();
        if(IMAGE) {
            saveImage(twoDImageData, width2DImageData, height2DImageData, disparityData, widthDisparityData, heightDisparityData);
            IMAGE = false;
        }
        if(ACQUISATION){
            QList<GstObservationBasic> detectorData = data->getObstaclesData();
            getObstacles(detectorData);
        }

        // 回调完成后,更新标志并通知等待的主线程
        std::lock_guard<std::mutex> lock(m_callbackMutex);
        m_callbackCompleted = true;
        m_callbackCondVar.notify_one();
    }
};

第二步:修改main函数

调用getImage后,直接调用新增的等待方法即可阻塞:

int main(){
    InterfaceColliseo interface;
    IMAGE = true;
    interface.getImage();
    interface.waitUntilCallbackDone(); // 这里会阻塞到回调执行完成
    return 0;
}

方案二:使用std::promise + std::future(适合一次性调用场景)

如果只需要单次等待,这种方式更轻量,不需要修改类的成员变量(如果允许修改类的话可以更优雅,否则可以用全局变量应急)。

优雅版(修改InterfaceColliseo类)

给getImage方法添加一个参数,用来传递完成通知的promise:

// 在InterfaceColliseo类里添加成员
std::shared_ptr<std::promise<void>> m_completionPromise;

// 修改getImage方法
void InterfaceColliseo::getImage(std::shared_ptr<std::promise<void>> completionPromise) {
    m_completionPromise = completionPromise;
    // 保留原有的getImage逻辑...
}

// 修改dataReceived方法
void InterfaceColliseo::dataReceived(std::shared_ptr<IData> data) {
    // 保留原有的业务逻辑...

    // 回调完成后触发promise
    if (m_completionPromise) {
        m_completionPromise->set_value();
        m_completionPromise.reset();
    }
}

然后修改main函数:

#include <future>

int main(){
    InterfaceColliseo interface;
    IMAGE = true;

    auto completionPromise = std::make_shared<std::promise<void>>();
    auto future = completionPromise->get_future();

    interface.getImage(completionPromise);
    future.wait(); // 阻塞直到回调触发promise

    // 可选:添加超时等待,避免无限阻塞
    // if (future.wait_for(std::chrono::seconds(5)) == std::future_status::timeout) {
    //     // 处理超时逻辑
    // }

    return 0;
}

应急版(不修改类,用全局变量)

如果无法修改InterfaceColliseo的代码,可以临时用全局变量传递promise(不推荐长期使用,因为全局变量线程不安全):

#include <future>

std::promise<void>* g_completionPromise = nullptr;

// 修改你的dataReceived回调
void InterfaceColliseo::dataReceived(std::shared_ptr<IData> data) {
    // 保留原有的业务逻辑...

    // 确保是本次main调用触发的回调
    if (IMAGE && g_completionPromise) {
        g_completionPromise->set_value();
        g_completionPromise = nullptr;
    }
}

int main(){
    InterfaceColliseo interface;
    IMAGE = true;

    std::promise<void> completionPromise;
    g_completionPromise = &completionPromise;
    auto future = completionPromise.get_future();

    interface.getImage();
    future.wait();

    return 0;
}

注意事项

  • 记得处理异常情况:比如回调可能因为错误不会触发,这时候可以给等待添加超时,避免程序永久阻塞。
  • 如果是多线程环境,要确保所有同步操作的线程安全,避免数据竞争。

内容的提问来源于stack exchange,提问作者Kamel Ghalgaoui

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:37:42