c++ - QThread interthread communication: strange behavior connecting to &QThread::quit vs connecting to a lambda [&thread] { thread->quit();} -
i have following setup:
int main(int argc, char *argv[]) { qcoreapplication a(argc, argv); // create dbmanager live entire // duration of application auto dbmanagerthread = std::make_unique<qthread>(); auto dbmanager = std::make_unique<dbmanager>(); dbmanager->movetothread(dbmanagerthread.get()); dbmanagerthread->start(); // initialization of application, create // inithelper object utilize dbmanager auto inithelper = new inithelper(); auto inithelperthread = new qthread(); inithelper -> movetothread(inithelperthread); // wire inithelper , thread qobject::connect(inithelperthread, &qthread::started, inithelper, &inithelper::run); qobject::connect(inithelper, &inithelper::finished, [&inithelperthread] { inithelperthread->quit();}); qobject::connect(inithelper, &inithelper::finished, inithelper, &inithelper::deletelater); qobject::connect(inithelperthread, &qthread::finished, inithelperthread, &qthread::deletelater); // wire inithelper , dbmanager qobject::connect(inithelper, &inithelper::querydb, dbmanager.get(), &dbmanager::processquery); qobject::connect(dbmanager.get(), &dbmanager::queryresult, inithelper, &inithelper::processqueryresult); // block until information gathered inithelperthread->start(); inithelperthread->wait(); std::cout << "initialization completed." << std::endl; // cleanup dbmanagerthread->quit(); qobject::connect(dbmanagerthread.get(), &qthread::finished, &a, &qcoreapplication::quit); return a.exec(); }
the idea have dbmanager doing asynchronous database accesses , hence utilized throughout entire application. during initialization of application need retrieve information database , i'd use existing dbmanager that.
however, since need information database create other objects, want block futher execution of main thread until inithelper has retrieved required information dbmanager.
since code above supposed to, don't think matters how inithelper , dbmanager implemented , have omitted them here.
what find confusing fact need use lambda in second line in 'wire inithelper , thread' part. if replace
qobject::connect(inithelper, &inithelper::finished, [&inithelperthread] { inithelperthread->quit();});
by
qobject::connect(inithelper, &inithelper::finished, inithelperthread, &qthread::quit);
apparently thread never shuts down , "initialization completed" never print stdout.
this output when using connection lambda:
inithelper: initialization started... dbmanager: processing query... inithelper: processing query result initialization completed.
whereas when connecting slot directly, output:
inithelper: initialization started... dbmanager: processing query... inithelper: processing query result
does know why there difference when connecting lambda instead of connecting slot directly? , how can write connect without lambda?
in code:
qobject::connect(inithelper, &inithelper::finished, [&inithelperthread] { inithelperthread->quit();});
is similar to:
qobject::connect(inithelper, &inithelper::finished, inithelperthread, &qthread::quit, qt::directconnection);
it means directly calling function instead of using event loop.
the reason, believe, "correct" code not work (i.e. when use qt::queuedconnection - default) because have not started qt event loop running calling a.exec();
to solve this, remove wait() function , move "startup" code startup class (a bit inithelper). connect signal finished of inithelper start() function (or whatever want call it) of startup class.
edit
you might able (just read similar):
int ret = a.exec(); inithelperthread->wait(); std::cout << "initialization completed." << std::endl; : other stuff : return ret;
Comments
Post a Comment