在单独的线程

时间:2017-07-17 20:53:06

标签: c++11 qt5 qtwidgets

我正在编写C ++ QT5 Widget桌面应用程序,当按下开始/停止按钮时,我需要在单独的线程上运行耗时的操作MainWindow::performLengthyOperation(bool)

这个耗时的操作在我的MainWindow.h / cpp中是一个相当冗长的方法。停止后台IO活动的操作大约需要6秒,启动大约需要2秒。在按下开始/停止按钮期间,UI没有响应。基本上,在我的按钮单击事件附加的插槽中,我需要执行以下逻辑。

void
MainWindow::on_pushButtonStart_clicked(bool checked)
{
    // temporarily disable the pushbutton 
    // until the lengthy operation completes
    mUI->pushButtonStart->setEnabled(false);

    if (checked) {
        // Start the timer tick callback
        mTickTimer.start(APP_TICK, this);
        mUI->pushButtonStart->setText("starting...");

        // This method needs to somehow run in its own QT thread
        // and when finished, call a slot in this MainWindow to
        // re-enable the pushButtonStart and change the statusBar
        // to indicate "runing..."
        performLengthyOperation(true);
        //mUI->pushButtonStart->setText("Stop")
        //mUI->statusBar->setStyleSheet("color: blue");
        //mUI->statusBar->showMessage("runing...");
    } else { // Stop the protocol threads
        // Stop the subsystem protocol tick timer
        mTickTimer.stop();
        mUI->pushButtonStart->setText("stopping...");
        // This method needs to somehow run in its own QT thread
        // and when finished, call a slot in this MainWindow to
        // re-enable the pushButtonStart and change the statusBar
        // to indicate "ready..."
        performLengthyOperation(false);
        // finally toggle the UI controls
        //mUI->pushButtonStart->setText("Start")
        //mUI->statusBar->setStyleSheet("color: blue");
        //mUI->statusBar->showMessage("ready...");
    }
}

当我在寻找有关如何执行此操作的示例时,我遇到了following article,但我无法将其调整到我的场景中,因为我需要以某种方式将MainWindow放入worker中,以便它可以访问其UI小部件等,这看起来有点矫枉过正。

我理想地寻找一种简单的异步运行lambda函数的方法,我可以放置这些耗时的操作(将主窗口作为参数传递)。这比使用QThreads和将对象移动到线程等更好。但是我对QT框架知之甚少,不知道这是安全还是可能的事情。

1 个答案:

答案 0 :(得分:2)

使用std :: async和lambdas:

std::future<void> future;作为成员添加到您的MainWindow类。

使用代码

添加广告位OnLengthyOperationPerformed
mUI->pushButtonStart->setText("Stop")
mUI->statusBar->setStyleSheet("color: blue");
mUI->statusBar->showMessage("runing...");
mUI->pushButtonStart->setEnabled(true);

添加信号void LengthOperationPerformed();并将其与MainWindow构造函数中的插槽连接。将Qt::QueuedConnection作为第五个连接参数传递,因为您想从主线程中调用您的插槽。

然后在on_pushButtonStart_clicked方法中你可以写:

future = std::async(std::launch::async, [this] {
  performLengthyOperation(true);
  emit LengthOperationPerformed();
});

与另一个电话相同。只需添加另一个插槽并发信号或将标志传递给插槽。

长动作将在另一个线程中运行,当它完成时,MainWindow接收信号并重新启用该按钮。