c++ - 如何在 Qt 主线程中正确执行 GUI 操作?

标签 c++ multithreading qt

我有一个包含两个线程的简单程序:

  1. 由 Qt QApplication::exec 操作的主要 GUI 线程
  2. boost::asio::io_service 操作的 TCP 网络线程

TCP 事件,例如连接或接收数据会导致 GUI 发生变化。大多数情况下,这些是 QLabel 上的 setText 和隐藏各种小部件。目前,我正在 TCP 客户端线程中执行这些操作,这似乎很不安全。

如何将事件正确发布到 Qt 主线程?我正在寻找 boost::asio::io_service::strand::post 的 Qt 变体,它将事件发布到 boost::asio::io_service 事件循环。

最佳答案

如果您的对象继承自 QObject,只需发出信号并将其连接(使用标志 Qt::QueuedConnection)到主线程中的插槽。信号和槽是线程安全的,应该优先使用。

如果它不是 QObject,那么您可以创建一个 lambda 函数(使用 GUI 代码)并使用单发 QTimer 将它排入主线程并在回调中执行它。这是我正在使用的代码:

#include <functional>

void dispatchToMainThread(std::function<void()> callback)
{
    // any thread
    QTimer* timer = new QTimer();
    timer->moveToThread(qApp->thread());
    timer->setSingleShot(true);
    QObject::connect(timer, &QTimer::timeout, [=]()
    {
        // main thread
        callback();
        timer->deleteLater();
    });
    QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
}

...
// in a thread...

dispatchToMainThread( [&, pos, rot]{
    setPos(pos);
    setRotation(rot);
});

原始信用https://riptutorial.com/qt/example/21783/using-qtimer-to-run-code-on-main-thread

请小心,因为如果删除对象,您的应用可能会崩溃。两个选项是:

  • 调用 qApp->processEvents();在移除以刷新队列之前;
  • 也使用 dispatchToMainThread 对删除进行排队;

关于c++ - 如何在 Qt 主线程中正确执行 GUI 操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34135624/

相关文章:

java - 使用 java.text.Collat​​or 并发排序时如何避免线程阻塞?

c# - 为什么这种递归方法在没有变量时会导致堆栈溢出错误?

java - 尽管创建了应该处于 sleep 状态的新线程,但在线程 sleep 时无法选择切换按钮

c++ - QtCreator 4.1.0 不显示 MainWindow 表单编辑器的 webengineview(QT 5.7)

c++ - QApplication::processEvents 在 Windows 中不工作

c++ - 如何比较两个双向迭代器的(顺序)?

c++ - 生成随机但不重复的数字 (C++)

c++ - CTAD、initializer_list、非显式构造函数和函数调用

c++ - 为什么我们需要 [basic.scope.class]/2?

qt - 如何安装Qt mobility?