对不起这篇文章的篇幅。但我现在被困了两天......
我正在开发一个Qt 4.6 Windows应用程序,它通过ActiveX与硬件设备进行通信。
当我发送命令时,设备会执行一些操作,当它完成时(最多可能需要一分钟),它会发出一个信号。我需要等待这个信号才能知道一切是否正常(或不是)并做了一些后果。
当用户单击按钮时,会向设备发送命令。显然,我不希望HMI冻结。
我确信我必须使用线程。所以我确定了三个主题:
这是类图:
以及显示我如何看待事物的序列图:
说明:
当用户启动我的应用程序时,将创建HMI。 HMI的构造函数调用Worker的构造函数。它构造硬件QAxObject。然后它构造了HardwareListener,提供了引用:QAxObject,QMutex和QWaitCondition。然后,Worker的构造函数将HardwareListener对象移动到另一个线程并启动它。最后,HMI的构造函数启动Worker的线程。
然后,当用户单击按钮时,HMI会向Worker发送信号。 Worker向硬件发送命令(该命令可能会阻塞线程几秒钟,这就是为什么我需要另一个线程中的HardwareListener不要错过信号的原因)。然后工人等待QWaitCondition(在锁定QMutex之后)。
之后,硬件设备向HardwareListener发送信号,该信号唤醒QWaitCondition。因此,Worker线程停止等待并完成其操作。最后,工人通知HMI。
问题:
未创建/启动Worker和HardwareListener线程。一切都在主线程中完成,显然,它不起作用。我不在线程之间交换任何特殊对象(因此不需要qRegisterMetaType()
)
问题:
我的设计是否可以接受?可能还有其他一些方法可以做,但在我看来,这是最直接的(考虑到复杂性)。
编辑:
我已更改代码以删除QThread
继承。我改为使用moveToThread()
方法。
现在线程运行正常。 HOWEVER 我有一个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.
SOLUTION:
答案 0 :(得分:0)
Inheriting from QThread is not good design.如果你正在做的工作计算量很大,我建议使用QThreadPool。我不是更好地使用异步设计。这意味着只调用从不阻塞的函数,而是连接到通知您发生了某些事情的信号。
因此,例如,一旦硬件完成,将命令发送到硬件并发出信号。如果硬件API不提供异步功能而不是使用线程。 QtConcurrentRun可以帮助解决这个问题。通常你不需要自己触摸线程;如果没有它就会变得更容易。