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 没有启动的主要内容,如果未能解决你的问题,请参考以下文章

在 QThread 中启动 QTimer

试图解决 QThread 的问题

如何在 QThread 中使用 QTimer?

从 QThread 启动 QProcess [重复]

使用 QNetworkAccessManager 时启动 QThread 失败

c ++ qthread同时启动2个线程