我怎么能通过提升来制作像QFutureWatcher这样的东西

时间:2014-06-09 06:21:31

标签: c++ qt boost

我想在后台执行一些繁重的任务而不会在等待返回值时阻止gui,使用QFutureWatcher,事情很简单

来自Qt5.3文档的例子

// Instantiate the objects and connect to the finished signal.
MyClass myObject;
QFutureWatcher<int> watcher;
connect(&watcher, SIGNAL(finished()), &myObject, SLOT(handleFinished()));

// Start the computation.
QFuture<int> future = QtConcurrent::run(...);
watcher.setFuture(future);

我怎么能做出类似&#34;完成&#34;在boost的帮助下QFutureWatcher的信号(我需要在主线程中执行handleFinished())?

虽然QFutureWatcher在那里并且踢,但我们的项目现在依赖于Qt3,Qt4和Qt5(从Qt3升级应用程序的优先级,Qt4到Qt5非常低),这就是我们想要实现后端的原因升级和标准库的任务

编辑1: 刚刚找到答案,boost :: future为这种场景提供了一个非常优雅的解决方案,只需使用future.then

future.then([](boost::future<int> f) { return print_value(f.get()); });

编辑2: 未来调用的函数然后在主线程中没有执行,我怎么能让它在主线程中执行呢?

2 个答案:

答案 0 :(得分:0)

你不需要任何库,特别是如果它是一次性的东西并且不用于迭代之间的同步或类似的东西:

volatile bool done = false;
volatile int retvalue = 0;

void workerThread() {
    retvalue = some_function_doing_math();
    done = true;
}

void parentLocationCalling() {
    done = false;
    myCustomThread.run(workerThread);
    for (;!done;) sleep(10);
    // retvalue now contains the result
}

如果你有C ++ 11,那么它更容易完成,因为你不需要任何特定于平台的代码(未经测试):

#include <thread>

void workerThread(int &ret) {
    ret = some_function_doing_math();
}

void parentLocationCalling() {
    int result;
    std::thread worker(workerThread, std::ref(result));
    worker.join();
}

当然,您可能仍希望在等待时处理窗口消息和/或更新窗口,这些示例中并未考虑这些消息。

答案 1 :(得分:0)

如果希望处理函数在主线程中运行,则必须在事件循环中。

在这种情况下你可以这样做:

(我使用C++11但可以使用boost::threadQThread轻松完成

struct Object:public QObject {


    Q_OBJECT
    std::thread thr;

    Object(QObject *parent):QObject(parent){}
    ~Object(){
       if(thr.joinable())
           thr.join();
    }
public slots:
    void handler(int);

};

    ...
    auto obj = new Object(parent); //store it somewhere  
    obj->thr=std::thread([](Object * obj){
                      int ret=run_something();
                      //PostEvent on the event queue where the obj Object resides
                      QMetaObject::invokeMethod(obj, "handler",
                                                Qt::QueuedConnection,
                                                Q_ARG(int,ret));
                     }
    ...