C++ 封送对Qt主线程的调用

C++ 封送对Qt主线程的调用,c++,qt,events,C++,Qt,Events,我将使用Qt的libcommuni包装到另一个不使用Qt的DLL项目中。据我所知,我需要运行Qt消息泵(通过QCoreApplication)以确保网络、信号等正常工作。然而,我遇到了一些问题,想知道如何做到这一点 基本上,我想在DLL中启动一个线程,它调用QCoreApplication::exec()并泵送所有Qt事件。然后,我想将对DLL的外部调用(位于不同线程上)封送到Qt主线程,这样我就可以安全地使用libcommuni 看起来推荐的方法是使用信号和插槽,但我一直无法让它工作。我在通过

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

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

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

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


你知道我做错了什么吗?我猜我不太理解Qt的线程模型。

当您使用
QObject::connect
而不指定连接类型时,它使用
Qt::AutoConnect
,如果信号和插槽在单个线程中,它会变成
Qt::DirectConnection
,或者变成
Qt::QueuedConnection
,如果它们在不同的线程中。所以,在你的例子中,我可以说,目前,当你把信号和插槽连接起来时,它们所属的对象都位于一个线程中

为了使
Qt::QueuedConnection
工作,您需要在包含插槽的线程中创建一个事件循环

使用QThread的主要方法有两种:

  • 您可以派生
    QThread
    并重写
    QThread::run
    。在这种情况下,您应该做几件事:

    • 创建线程对象时,不要指定父对象;手动删除此对象
    • 在线程的构造函数中调用
      moveToThread(this)
    • 在线程的
      run
      方法中,在所有初始化之后,但在所有删除之前调用exec;调用
      QThread::quit
      后,线程将立即离开
      exec
  • 在调用
    QThread::start
    之前,您可以派生
    QObject
    ,创建
    QThread
    对象,并在对象上调用
    QThread::moveToThread
    (顺便说一句,应该在不指定父对象的情况下创建该对象)

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

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