QThread 没有启动
Posted
技术标签:
【中文标题】QThread 没有启动【英文标题】:QThread doesn't start 【发布时间】:2013-04-09 14:40:14 【问题描述】:很抱歉这篇文章的长度。但是我现在被困了两天......
我正在开发一个通过 ActiveX 与硬件设备通信的 Qt 4.6 Windows 应用程序。
当我发送命令时,设备会执行一些操作,完成后(可能需要一分钟)它会发出信号。我需要等待这个信号才能知道一切是否正常(或不正常)并相应地采取一些措施。
当用户单击按钮时,会向设备发送一条命令。显然,我不希望 HMI 死机。
我确信我必须使用线程。所以我确定了三个线程:
-
人机界面对应的主线程
硬件控制器(在发送命令后锁定并等待信号)
一个硬件通知监听器,不断从硬件获取信号并解锁线程 2
这是类图:
还有一个序列图来展示我如何看待事物:
说明:
当用户启动我的应用程序时,HMI 就创建好了。 HMI的构造函数调用Worker的构造函数。它构造硬件 QAxObject。然后它构造了HardwareListener,给出了引用:QAxObject、QMutex 和QWaitCondition。然后 Worker 的构造函数将 HardwareListener 对象移动到另一个线程并启动它。最后,HMI的构造函数启动Worker的线程。
然后,当用户单击按钮时,HMI 会向 Worker 发送信号。 Worker 向硬件发送一个命令(该命令可能会阻塞线程几秒钟,这就是为什么我需要另一个线程中的 HardwareListener 不要错过信号)。然后 Worker 等待 QWaitCondition(在锁定 QMutex 之后)。
之后,硬件设备向 HardwareListener 发送一个信号,唤醒 QWaitCondition。因此,Worker 线程停止等待并完成其操作。最后,Worker 通知 HMI。
问题:
Worker 和 HardwareListener 线程未创建/启动。一切都在主线程中完成,所以很明显,它不起作用。我不在线程之间交换任何特殊对象(所以不需要qRegisterMetaType()
)
问题:
我的设计可以接受吗?可能还有其他一些方法可以做,但在我看来这是最直接的(考虑到复杂性)。
编辑:
我已更改代码以删除 QThread
继承。我改用moveToThread()
方法。
现在线程工作正常。 但是我有一个 ActiveX 错误:QAxBase: Error calling IDispatch member NewProject: Unknown error
。
似乎与硬件的接口已损坏...有什么想法吗?
Here is something interesting:
You cannot move a QAxObject to another thread once it has been created.
解决方案:
Here is what I have found.
【问题讨论】:
可以看到一些代码,也不需要移动到线程。有一些关于不从 QThread 继承的帖子。 你必须提供一些代码。我假设你使用 QThread。你用QThread实现worker和listener之间的通信是怎样的?您是否将它们移至新线程?如果你继承 QThread - 然后停止这样做。阅读带有工人示例的文档。 你想看代码的哪一部分?我已经尝试过不从 QThread 继承而只是调用moveToThread()
。它适用于 Worker,但不适用于 HardwareListener。你能解释一下为什么不需要线程吗?
【参考方案1】:
Inheriting from QThread is not good design. 如果您正在做的工作计算量很大,我建议您使用QThreadPool。我并不比使用异步设计更好。这意味着只调用永远不会阻塞的函数,而是连接到通知您发生了某些事情的信号。
例如,将命令发送到硬件并在硬件完成后发出信号。如果硬件 API 不提供异步函数,那么您将无法使用线程。 QtConcurrentRun 可以提供帮助。通常您不需要自己触摸线程;没有它会容易得多。
【讨论】:
是的,硬件 API 不提供异步函数。这就是重点......QtConcurrentRun
似乎不太好用。我习惯于使用 C 和 Java 进行开发,但我对 Qt 编程很陌生。以上是关于QThread 没有启动的主要内容,如果未能解决你的问题,请参考以下文章