1

抱歉这篇文章的长度。但是我现在被困了两天......

我正在开发一个通过 ActiveX 与硬件设备通信的 Qt 4.6 Windows 应用程序。

当我发送命令时,设备会执行一些操作,完成后(可能需要一分钟)它会发出信号。我需要等待这个信号才能知道一切是否正常(或不正常)并因此采取一些行动。

当用户单击按钮时,命令会发送到设备。显然,我不希望 HMI 冻结。

我确信我必须使用线程。所以我确定了三个线程:

  1. HMI对应的主线程
  2. 硬件控制器(在发送命令后锁定并等待信号)
  3. 一个硬件通知监听器,不断从硬件获取信号并解锁线程 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.

解决方案:

这是我发现的。

4

1 回答 1

0

从 QThread 继承并不是好的设计。如果您正在做的工作计算量很大,我建议使用QThreadPool。我并不比使用异步设计更好。这意味着只调用永远不会阻塞的函数,而是连接到通知您发生了某些事情的信号。

因此,例如将命令发送到硬件并在硬件完成后发出信号。如果硬件 API 不提供异步函数,那么您将无法使用线程。 QtConcurrentRun可以帮助解决这个问题。通常您不需要自己触摸线程;没有它会容易得多。

于 2013-04-09T15:16:00.717 回答