抱歉这篇文章的长度。但是我现在被困了两天......
我正在开发一个通过 ActiveX 与硬件设备通信的 Qt 4.6 Windows 应用程序。
当我发送命令时,设备会执行一些操作,完成后(可能需要一分钟)它会发出信号。我需要等待这个信号才能知道一切是否正常(或不正常)并因此采取一些行动。
当用户单击按钮时,命令会发送到设备。显然,我不希望 HMI 冻结。
我确信我必须使用线程。所以我确定了三个线程:
- 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
.
似乎与硬件的接口被破坏了......有什么想法吗?
You cannot move a QAxObject to another thread once it has been created.
解决方案:
这是我发现的。