2

我将使用 Qt 的 libcommuni 包装在另一个不使用 Qt 的 DLL 项目中。据我所知,我需要运行 Qt 消息泵(通过QCoreApplication)以确保网络、信号等正常工作。但是,我在弄清楚如何做到这一点时遇到了一些问题。

基本上,我想在 DLL 中启动一个线程,它调用QCoreApplication::exec()和泵送所有 Qt 事件。然后,我想将对位于不同线程上的 DLL 的外部调用编组到 Qt 主线程,这样我就可以安全地使用 libcommuni。

看起来推荐的方法是为此使用信号和插槽,但我一直无法让它工作。QObject我在通过 DLL 调用的类上创建了一个信号,并将其连接到QThread运行 Qt 消息泵的插槽。但是,如果我Qt::QueuedConnection在连接信号和插槽时指定,则在发出信号时永远不会传递消息。如果我完全省略Qt::QueuedConnection,插槽会立即在调用线程而不是 Qt 主线程上调用。

我还尝试显式调用QCoreApplication::postEvent()DLL 线程以将事件发送到 Qt 主线程,但event(QEvent)从未在 target 中调用QThread

关于我在这里做错了什么的任何想法?我猜我不太了解 Qt 的线程模型。

4

1 回答 1

1

当您在QObject::connect不指定连接类型的情况下使用时 - 它使用Qt::AutoConnectionQt::DirectConnection如果信号和插槽在单个线程中,则变为Qt::QueuedConnection,如果它们在不同线程中,则变为 。因此,就您而言,我可以说,目前,当您将信号与插槽连接时,它们所属的对象位于一个线程中。

为了Qt::QueuedConnection工作,你需要一个线程中的事件循环,其中包含插槽。

使用 QThread 主要有两种方式:

  1. 您可以派生QThread和重写QThread::run. 在这种情况下,您应该做几件事:

    • 创建线程对象时,不要指定父对象;手动删除此对象。
    • 在你线程的构造函数调用moveToThread(this)中。
    • run在所有初始化之后但在所有删除之前,在您的线程的方法调用 exec 中;线程将exec在您调用后立即离开QThread::quit
  2. QObject可以在QThread调用.QThread::moveToThreadQThread::start

在您的情况下,我建议使用第二种方法。

那是关于线程的,但我不太确定,您的问题与QCoreApplication::exec.

于 2013-04-07T05:16:54.823 回答