0

Im my mainthread, I have a Qt window running, which is calling my background thread (network service) and is eventually expecting responses which should be reflected in the UI:

// runs in main (GUI) thread
void QTServer::onButtonClick(){
    srv->request(msg, 
        [this]
           (std::shared_ptr<message> msg){
              this->ui.txtResponse->setText("received a response" + msg.data());
            });
}

The network service is as follows:

std::function<void(std::shared_ptr<message>)> delegate_;

void NetworkService::request(message& msg,std::function<void(std::shared_ptr<message> msg)> fn)
{
    // send the request to the socket and store the callback for later
    // ...
    this->delegate_ = fn;
}

void NetworkService::onResponseReceived(std::shared_ptr<message> responseMsg)
{
    // is called from the background thread (service)
    // Here I would like to call the lambda function that the service stored somewhere (currently as an std::func member)

    // psuedo: call In Main Thread: delegate_(responseMsg);
}

How does that work? Does it even work?

I know that you can use QMetaObject::invokeMethod(this, "method", Qt::QueuedConnection to call a function in the mainthread, so I tried the following:

void NetworkService::onResponseReceived(std::shared_ptr<message> responseMsg)
{
    QMetaObject::invokeMethod(this, "runInMainThread", Qt::QueuedConnection, QGenericArgument(), Q_ARG(std::function<void(std::shared_ptr<message>)>, delegate_));
}

How do I pass the responseMsg here as an argument for _delegate?

 void QTServer::runInMainThread(std::function<void(std::shared_ptr<message>)> f) {
    f(); 
}

How to get rid of "No function with these arguments" error?

IAmInPLS
  • 4,051
  • 4
  • 24
  • 57
netik
  • 1,736
  • 4
  • 22
  • 45

2 Answers2

1

remove QGenericArgument() - it's internal helper class. also you have to register your own types in order to use Q_ARG or send data as void* then cast it back.

Q_ARG(void*, delegate_)

2nd question - f is function which takes one argument - std::shared_ptr, and f() - call without argument, so add default argument

jonezq
  • 344
  • 1
  • 5
-1

I believe the recommended way for what you are trying to achieve in QT is by using signals and slots in combination with QThread. For example:

MyObject * myObject = new MyObject(); //your worker
QThread * myThread = new QThread(); //your thread
myObject->moveToThread(myThread);

QObject::connect(myThread, SIGNAL(started()), myObject, SLOT(startWorking())); //when thread starts, invoke the working method
QObject::connect(myObject, SIGNAL(stoppedWorking()), this, SLOT(stoppedWorking())); //when worker signals it finished, invoke slot in main

QObject::connect(myObject, SIGNAL(stoppedWorking()), myThread, SLOT(quit())); //quit the thread when worker signals that it finished
QObject::connect(myObject, SIGNAL(gproxyExiting()), gproxy, SLOT(deleteLater())); //cleanup
QObject::connect(myThread, SIGNAL(finished()), myThread, SLOT(deleteLater())); //cleanup

This way the whole lifecycle is managed automatically for you and you can define whatever signals inside the worker and slots on the main thread to communicate with each other.

cen
  • 2,873
  • 3
  • 31
  • 56