【发布时间】: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.
解决方案:
【问题讨论】:
-
可以看到一些代码,也不需要移动到线程。有一些关于不从 QThread 继承的帖子。
-
你必须提供一些代码。我假设你使用 QThread。你用QThread实现worker和listener之间的通信是怎样的?您是否将它们移至新线程?如果你继承 QThread - 然后停止这样做。阅读带有工人示例的文档。
-
你想看代码的哪一部分?我已经尝试过不从 QThread 继承而只是调用
moveToThread()。它适用于 Worker,但不适用于 HardwareListener。你能解释一下为什么不需要线程吗?