我正在使用
QtSerialPort库通过USB与虚拟COM端口通话.当使用QtSerialPort给出的示例项目进行测试时,COM端口返回数据并正常工作,但是当我作为项目的一部分运行时,COM端口将失败.
我检查了实例链和线程,导致QtSerialPort被实例化,发现有点奇怪.结果如下.
main() MainWindow (Thread 0xbf8dbe0) // Thread "A" HardwareManager (Thread 0xbf8dbe0) // Thread "A" QSerialPort (Thread 0xbfb95f0) // Thread "B" !?
在我的代码中,main()函数实例化一个MainWindow,它又实例化了一个HardwareManager并将其存储为一个私有变量.当HardwareManager被实例化时,它还实例化QSerialPort实例,以便它可以正确地与COM端口通信.
但是,您会注意到我的QSerialPort与父对象不同的线程,以及它的父对象(它在线程B中,而祖先在线程A中).我认为这个其他线程导致我的信号/插槽失败.如果我dumpObjectInfo,它列出了我的信号/插槽设置,但事件永远不会触发.
this->serial = new QSerialPort(); connect(this->serial,SIGNAL(readyRead()),this,SLOT(readSerialData());
以上是我用来创建新的串行端口并将其连接到正确的插槽的代码.实际的波特率,奇偶校验和数据/停止位配置分别发生(正常工作,如QtSerialPort提供的示例应用程序中所测试的).
有没有人有任何洞察,为什么这个特定的对象(QSerialPort实例)正在不同的线程中实例化?我尝试过“moveToThread”来切换线程关联,但是似乎没有任何效果.
我也做了post on the Qt Project Forums,但还没有任何有用的回应.
任何帮助是赞赏.
编辑:
以下是呼叫链中的相关代码:
// main() QApplication a(argc,argv) MainWindow window = new MainWindow(); // [1] MainWindow.show(); return a.exec(); // MainWindow::MainWindow() [1] this->toolController = new QtToolController(this); HardwareManager *manager = new HardwareManager(this->toolController); // [2] // HardwareManager::HardwareManager() [2] this->serial = new QSerialPort(); connect(this->serial,SLOT(readSerialData()));
当QSerialPort准备好读取(它有数据提供)时,它会触发readyRead信号(至少应该是).这个信号在Qt示例项目中正常启动,但我从来没有在我的应用程序中获取信号.我相信我没有得到信号的原因是因为这些线程问题.
解决方法
您可以使用
QueuedConnection捕获来自不同线程的信号.
connect(this->serial,SLOT(readSerialData()),Qt::QueuedConnection);
这样,当控件返回到它的事件循环时,这个插槽应该在主线程的上下文中执行.
此外,this post似乎建议您不要为QtSerialPort设置父级(可以说是因为moveToThread不适用于具有父级的QObjects).