I am writing an RPC-like program that uses the Qt signal slot, when using a client program to call the server, a function is executed, and I need to print the value of this function on the QtableWidget, so I use emit to transmit signals in this function, but I find that the slot function is not executed. This seems to be related to multithreading.
update: I found that I made a mess of the code, here to simplify. I use a static class method to emit a signal so the code looks a little bit tricky.
// service.cpp file
#include "service.h"
multipleService* multipleService::getInstance = nullptr;
int add(int a, int b) {
return a + b;
}
multipleService::multipleService() {
getInstance = this; // for static method to emit signal
bool ok = connect(this, &multipleService::internalMessageOutput, this, &multipleService::messageOutputFunc, Qt::AutoConnection);
}
// implement service
void multipleService::AddService(ServiceType::Request& request, ServiceType::Response& response) {
// do some stuff ... get response
emit getInstance->internalMessageOutput(QString(response));
}
void multipleService::messageOutputFunc(QString msg) {
emit getInstance->messageOutput(msg);
}
// service.h file
#pragma once
#include <stdio.h>
#include <string.h>
// some declarations
class multipleService :public QObject {
Q_OBJECT
public:
multipleService();
~multipleService();
static void AddService(ServiceType::Request& request, ServiceType::Response& response);
void messageOutputFunc(QString);
private:
static multipleService* getInstance;
signals:
void messageOutput(QString);
void internalMessageOutput(QString);
};
And in the mainwindow.cpp file, I use create_service to behave like a server in RPC. And this actually works fine. once emit getInstance->internalMessageOutput(QString(response)); executes,the signal func executes.
//mainwindow.cpp in main thread
multipleService* s = new multipleService();
connect(s, &multipleService::messageOutput, this, &serviceThread::outputMessage);
auto service = node.create_service<ServiceType>(service_name, multipleService::AddService, qoS);
But I want to create a multithread so I changed the code like
// mainwindow.cpp file in main thread
QThread* thread = new QThread; //create a thread
serviceThread* myThread = new serviceThread(this);// create a class which derives from QObject and move it to the thread
//connect start signal with a lambda func
connect(thread, &QThread::started, myThread, [&myThread, SERVICE_NAME]()
{ std::string a = SERVICE_NAME;
char* AddServiceName = (char*)a.data();
myThread->createService("NODE", AddServiceName, 10);
});
// start a thread and this will call the slot func
thread->start();
myThread->moveToThread(thread);
I create a serviceThread.cpp and new serviceThread and move it to a thread to support multithread but emit getInstance->internalMessageOutput(QString(response)),the slot func doesn't execute.
//serviceThread.cpp file
void serviceThread::createService(const char* nodeName, const char* service_name, int historyDepth) {
// do some declaration
multipleService* s = new multipleService();
connect(s, &multipleService::messageOutput, this,
&serviceThread::outputMessage);
auto service = node.create_service<ServiceType>(service_name,
multipleService::AddService, qos);
if (service) {
service->start();
}
else {
// error
return;
}
while (true)
{ //
if (QThread::currentThread()->isInterruptionRequested())
{
break;
}
}
}
I have tried to change the connect type to Qt::QueuedConnection and this also failed. I also set a breakpoint on the line and it literally executed.
update: OK,I find something wrong with the while loop in the multithread, I use QCoreApplication::processEvents(QEventLoop::AllEvents, 10); in the loop to temporirally solve this problem. Are there any other solutions?
One of problems I see right away is
mainwindow.cppcode:If you look up documention on website, you must pay attention, they mentioned that. You can't move a parented
QObjectand you cannot move aQWidgetat all. SinceserviceThreadis aQObject,myThreadcannot be moved - it is parented to main window now, which is part of main thread.My usual approach to this is
QObject-derived class, let's call itManager,Managerto the worker thread,QThreadtoManagers slots.Managerwould create the rest of objectsCode for an old project, redacted.. sorry for Qt4 style
connect()What
Manager::startdoes: