运行 单独线程上的 QT MainWindow 方法
Running a QT MainWindow method on a separate thread
我正在编写一个 C++ QT5 小部件桌面应用程序,当按下 start/stop 按钮时,我需要在单独的线程上 运行 一个耗时的操作 MainWindow::performLengthyOperation(bool)
。
这个耗时的操作在我的MainWindow中是一个相当冗长的方法。h/cpp。停止后台 IO activity 的操作大约需要 6 秒,启动大约需要 2 秒。在按下 start/stop 按钮期间,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 放入工作程序以便它可以访问它的 UI 小部件等,这似乎有点矫枉过正。
理想情况下,我正在寻找一种简单的方法来异步 运行 lambda 函数,我可以在其中放置这些耗时的操作(将主窗口作为参数传递)。这比使用 QThreads 和将对象移动到线程等更可取。但我对 QT 框架的了解还不够多,无法知道这样做是否安全或可行。
使用 std::async 和 lambdas:
将 std::future<void> future;
作为成员添加到您的主窗口 class。
添加插槽 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 接收信号并重新启用按钮。
我正在编写一个 C++ QT5 小部件桌面应用程序,当按下 start/stop 按钮时,我需要在单独的线程上 运行 一个耗时的操作 MainWindow::performLengthyOperation(bool)
。
这个耗时的操作在我的MainWindow中是一个相当冗长的方法。h/cpp。停止后台 IO activity 的操作大约需要 6 秒,启动大约需要 2 秒。在按下 start/stop 按钮期间,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 放入工作程序以便它可以访问它的 UI 小部件等,这似乎有点矫枉过正。
理想情况下,我正在寻找一种简单的方法来异步 运行 lambda 函数,我可以在其中放置这些耗时的操作(将主窗口作为参数传递)。这比使用 QThreads 和将对象移动到线程等更可取。但我对 QT 框架的了解还不够多,无法知道这样做是否安全或可行。
使用 std::async 和 lambdas:
将 std::future<void> future;
作为成员添加到您的主窗口 class。
添加插槽 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 接收信号并重新启用按钮。