2016-04-01 3 views
0

Im мой mainthread, у меня есть окно Qt, которое вызывает мой фоновый поток (услуга сети) и в конечном итоге ожидает ответов, которые должны быть отражены в UI:Вызов lambda/std :: function в основном потоке пользовательского интерфейса из фоновой темы

// 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(); 
} 

Как избавиться от ошибки «Нет функции с этими аргументами»?

ответ

1

удалить QGenericArgument() - это внутренний вспомогательный класс. также вам необходимо зарегистрировать свои собственные типы, чтобы использовать Q_ARG или отправить данные как void *, а затем вернуть его обратно.

Q_ARG(void*, delegate_) 

второй вопрос - е есть функция, которая принимает один аргумент - станд :: shared_ptr, и F() - вызов без аргументов, поэтому добавьте аргумент по умолчанию

+0

хмм, он говорит "нет конструктора доступны", если я пытаюсь 'Q_ART (пустота *, delegate_)' – netik

+0

передачи адрес Q_ARG (пустота *, & delegate_), а затем использовать reinterpret_cast <аннулируется (станд :: shared_ptr ) *> – jonezq

-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 

Таким образом, весь жизненный цикл управляется автоматически для вас, и вы можете определять любые сигналы внутри рабочих и пазов на главном потоке, чтобы общаться друг с другом.

Смежные вопросы