使用Qt GUI打包线程程序

时间:2014-12-29 18:04:57

标签: c++ multithreading qt qthread qtconcurrent

我有一个工作,完成的应用程序,它使用多个boost线程,并且可以通过命令行界面正常工作。

我用#34;包装"打包了这个程序。 class,以便我可以从Qt主窗口运行程序中的函数。

例如:

netWrap.getImgs(ui->sampleNameEdit->text().toStdString());

这会从文本框中使用参数sampleName从网络程序中获取图像,并从按钮触发的插槽中调用。

这一切都运行正常,但是,某些功能(例如上面的功能)可能需要大约20秒才能运行,这会挂起GUI。我希望不要挂起GUI。

显而易见的选择是使用QThread,但我不想在程序中添加额外的类,因为这只是一个简单的前端。有没有办法可以在线程中运行此函数并等待终止信号而不挂起GUI?

编辑:QFutures:

 QFuture<int> run = QtConcurrent::run(&(netWrap.getImgs), ui->sampleNameEdit->text().toStdString());

这会产生4个错误,最相关的可能是:

error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function.  Say '&networkWrapper::getImgs' [-fpermissive]
     QFuture<int> run = QtConcurrent::run(&(netWrap.getImgs), ui->sampleNameEdit->text().toStdString());

error: no matching function for call to 'run(int (networkWrapper::*)(std::string), std::string)'
     QFuture<int> run = QtConcurrent::run(&(netWrap.getImgs), ui->sampleNameEdit->text().toStdString());

2 个答案:

答案 0 :(得分:3)

你没有将QThread子类化为在不同的线程中运行某些东西。 QThread通过信号/插槽使用。

http://doc.qt.io/qt-5/qthread.html#started

默认QThread :: run()启动一个事件循环,允许您处理其他线程中的网络事件。这意味着您连接到QThread :: started信号,启动您的请求并在不同的线程中处理它们。然后,您可以使用另一个信号向您的主GUI线程发出信号,告知您已完成并且数据可用。

如果你需要的是在另一个线程中调用某个函数,那么使用Qt Concurrent。这比QThread更容易使用。

http://doc.qt.io/qt-5/qtconcurrent.html#run

void my_function(int a, double b) {
     .... do something in another thread ....
}
    ....
    auto some_function = std::function<void(int, double)>(&my_function);
    QFuture<void> ret = QtConcurrent::run(some_function, 10, 20.0);
    ....

或者不使用std :: function,只需直接使用普通函数指针

QFuture<void> ret = QtConcurrent::run(&my_function, 10, 20.0);

要调用类成员,它也同样简单,

class Foo {
public:
     void foo(int a) {}
};

...
Foo *foo_instance = new Foo;
QFuture<void> ret = Qtconcurrent::run(foo_instance, &Foo::foo, 10);
...

您的函数正在另一个线程中运行。就这么简单。

注意:不要从非GUI线程访问/操作GUI类。

答案 1 :(得分:1)

您应该提供指向对象的指针,以及类成员函数的地址和所需的参数,如:

QFuture<void> future = QtConcurrent::run(netWrap, &networkWrapper::dbsChanged, ui->sampleNameEdit->text().toStdString());

您可以检查未来代表的异步计算的状态,如:

if(future.isRunning())
{
    // It is currently running
}

或者等待它完成:

future.waitForFinished();

QtConcurrent::run()不会像QtConcurrent::mappedReduced()那样自动提供进度信息。但是您可以使用信号拥有自己的进度报告机制。

要通知终止,从功能中发出信号表明它已经完成是一种简单的方法。