繁体   English   中英

是否可以从渲染线程强制执行主线程(GUI 线程)?

[英]Is it possible to force execute main thread (GUI thread) from render thread?

我们有在渲染线程中执行的命令队列,直接在QQuickWindow::beforeRenderingQQuickWindow::afterRendering ,命令对数据模型进行更改,当数据模型更改时,它立即通知我们的自定义 OpenGL 渲染引擎同步数据。

问题是当数据模型更改时,它也会通知旨在更新 UI 的订阅者。 但是从不同的线程更新 UI 是一种容易出错的方法。 一种方法是使用Qt::QueuedConnection 这也很容易出错,因为执行时模型可能会进入远态。

设计与这个例子非常相似。

例如,是否可以从渲染线程更新与 QML 链接的QStadardItemModel

有可能,您可以使用QMetaObject::invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr)QMetaObject::invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr)重载来QMetaObject::invokeMethod

对于上下文,您需要传递一个生活在要运行函数的线程上的对象。 对于 GUI 线程, QCoreApplication::instance()是一个不错的选择。 对于连接类型,根据您的需要使用Qt::QueueConnectionQt::BlockingQueuedConnection (您是否需要调用阻塞)。 如果您正在使用Qt::BlockingQueuedConnection ,请确保您当前不在主线程中(如果是这种情况,您可以进行检查并通过Qt::DirectConnection )。

而对于函子来说,一个 lambda 就可以解决问题。

例如:

qDebug() << "1 main thread" << QThread::currentThreadId();
QtConcurrent::run([] {
    qDebug() << "1 QtConcurrent thread" << QThread::currentThreadId();

    QMetaObject::invokeMethod(QCoreApplication::instance(), [] {
        qDebug() << "invokeMethod thread" << QThread::currentThreadId();
    }, Qt::BlockingQueuedConnection);

    qDebug() << "2 QtConcurrent thread" << QThread::currentThreadId();
});
qDebug() << "2 main thread" << QThread::currentThreadId();

这输出:

1 main thread 0x1c7c
2 main thread 0x1c7c
1 QtConcurrent thread 0x19ec
invokeMethod thread 0x1c7c
2 QtConcurrent thread 0x19ec

您可以从Calling Qt Functions From Unix Signal Handlers 中获得灵感

您可能有一些中央数据结构,例如一些包含lambda 表达式的std::deque 让我们称之为您的待办事项清单。 该待办事项列表还管理一个管道(7) (所以两个文件描述符)。

您将使用适当的std::mutex保护该待办事项列表并使用std::condition_variable

您将通过使用一些pipe(7)fifo(7)在渲染线程和主 Qt 线程之间进行同步,然后使用(在主线程中)一些QSocketNotifier进行同步。 在向您的 todolist 添加闭包时,渲染线程还会向该 fifo 或管道写入(2)一些字节,并且主线程将使用QSocketNotifier读取(2)它,然后从您的 todo 列表中获取(弹出)一个闭包并运行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM