Marshal调用Qt主线程

时间:2013-04-07 04:22:44

标签: c++ qt events

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

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

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

我还尝试在DLL线程上显式调用QCoreApplication::postEvent()来向Qt主线程发送事件,但永远不会在目标event(QEvent)中调用QThread

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

1 个答案:

答案 0 :(得分:1)

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

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

使用QThread有两种主要方式:

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

    • 创建线程对象时,不要指定parent;手动删除此对象。
    • 在线程的构造函数中调用moveToThread(this)
    • 在所有初始化之后,但在所有删除之前,在线程的run方法调用exec中;致电exec后,主题将立即离开QThread::quit
  2. 您可以在调用{之前'派生QObject,创建QThread对象,并在您的对象上调用QThread::moveToThread(顺便说一下,应该创建它而不指定父对象) {1}}。

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

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