我是我的主线程,我有一个Qt窗口正在运行,它正在调用我的后台线程(网络服务),并最终期待应该在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());
});
}
网络服务如下:
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);
}
这是如何工作的?它甚至可以工作吗?
我知道您可以使用QMetaObject::invokeMethod(this, "method", Qt::QueuedConnection
来调用mainthread中的函数,所以我尝试了以下内容:
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_));
}
如何在此处传递responseMsg作为_delegate的参数?
void QTServer::runInMainThread(std::function<void(std::shared_ptr<message>)> f) {
f();
}
如何摆脱“没有这些参数的函数”错误?
答案 0 :(得分:1)
删除QGenericArgument() - 它是内部帮助器类。 您还必须注册自己的类型才能使用Q_ARG或将数据作为void *发送回来。
Q_ARG(void*, delegate_)
第二个问题 - f是一个函数,它接受一个参数--std :: shared_ptr,和f() - 不带参数调用,所以添加默认参数
答案 1 :(得分:-1)
我认为在QT中尝试实现的推荐方法是将信号和插槽与QThread结合使用。例如:
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
这样就可以自动管理整个生命周期,您可以定义工作线程内的任何信号和主线程上的插槽,以便相互通信。