我正在编写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框架知之甚少,不知道这是安全还是可能的事情。
答案 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接收信号并重新启用该按钮。