Qt中app.exec()机制与ZMQ服务端客户端通信循环实现问题
app.exec()的作用就是启动Qt的主事件循环,确实会一直阻塞直到程序退出才返回,所以你写在它前面的通信逻辑只会执行一次,这是正常现象。
报错原因
虽然QThread本身继承自QObject,但你自定义的MyThread子类使用了Qt的槽函数特性,必须在类定义中添加Q_OBJECT宏,Qt的元对象系统才能正确处理类的信号槽逻辑,缺少这个宏就会触发你遇到的编译错误。另外你当前的线程用法和通信逻辑也有问题,按下面的步骤修改即可实现循环通信:
1. 修改thread.h
#include <QThread> class MyThread : public QThread{ Q_OBJECT protected: // run是QThread的内置虚函数,直接重写即可,不需要定义为槽 void run() override; };
2. 修改thread.cpp的run实现
void MyThread :: run() { zmq::context_t context(1); zmq::socket_t socket(context, ZMQ_REP); socket.bind("tcp://*:2424"); zmq::message_t request; // 加死循环,处理完一个请求后继续等待下一个 while(true) { // Wait for next request from client cout << "Waiting for the next request ." << endl; socket.recv(&request); cout << "Waiting for the next request.. " << endl; string replyMessage = string(static_cast<char *>(request.data()), request.size()); // Print out received message cout << "Received from client (Python): " + replyMessage << endl; sleep(1); // Send reply back to client string msgToClient("W"); zmq::message_t reply(msgToClient.size()); memcpy((void *) reply.data(), (msgToClient.c_str()), msgToClient.size()); socket.send(reply); } // 不需要加exec(),你这里用阻塞recv等待请求,不需要Qt的线程事件循环 }
3. 修改main.cpp中的线程调用逻辑
你之前混淆了QThread的两种使用方式,重写run()的用法不需要moveToThread,直接启动线程即可:
// 替换原来的线程创建代码 MyThread *zmqThread = new MyThread(); zmqThread->start();
注意事项
- 添加
Q_OBJECT宏后,必须清理之前的编译缓存,重新执行qmake再编译,否则还可能出现元对象相关的编译错误。 - 如果需要把线程中收到的消息传递到UI层更新界面,直接在MyThread中定义信号,触发后通过信号槽传递到主线程即可,Qt的信号槽天生支持跨线程安全通信。
- 不要在这个子线程中操作任何UI相关的控件,所有UI操作都必须在主线程执行。
内容的提问来源于stack exchange,提问作者noobie
相关产品推荐
相关产品推荐

