c++ - Is myDesign for thread communication acceptable? -
i trying create , working qt
design communication between several threads. have preference window, emits different signals on clicking on apply. example 1 creating sql connection , 1 changing other stuff. want change preferences in background thread in different classes , after making changes shall emit result signal. in preferences window want wait until signals received (either true or false result) before either close window or print error message.
i tried draw design in attached picture. correct way purpose? struggling way of waiting results. thinking of creating kind of array save every result , check array, whether signals received. sounds pretty ugly... there better method wait until signals received?
also idea make classes in background thread singelton
? need 1 instance of classes , make access classes pretty easy since not need drag pointers every object, needs know classes.
also know, whether idea store public member in mysql class, tells me, whether database connected , access directly out of other threads?
thank you!
the qstatemachine
want: can transition between states when receives signals.
the background threads might not need based on classes, , no matter shouldn't singletons. can give functor qtconcurrent::run
, , emit signal there.
the logic should factored out separate qobject
:
// https://github.com/kubao/stackoverflown/tree/master/questions/thread-jobs-39109247 #include <qtwidgets> #include <qtconcurrent> #include <functional> class controller : public qobject { q_object qstatemachine m_machine{this}; qstate s_init{&m_machine}; qstate s_busy{&m_machine}; qstate s_idle{&m_machine}; int m_activetasks = 0; void ontaskstarted() { ++ m_activetasks; emit taskrunning(); } void ontaskdone() { if (--m_activetasks == 0) emit alltasksdone(); } q_signal void taskrunning(); q_signal void alltasksdone(); q_signal void task1done(int result); q_signal void task2done(int result); public: q_signal void active(); q_signal void finished(); q_slot void dotask1() { ontaskstarted(); qtconcurrent::run([this]{ qthread::sleep(2); // pretend work emit task1done(42); }); } q_slot void dotask2() { ontaskstarted(); qtconcurrent::run([this]{ qthread::sleep(5); // pretend work emit task2done(44); }); } controller(qobject * parent = nullptr) : qobject{parent} { // describes state machine s_init.addtransition(this, &controller::taskrunning, &s_busy); s_idle.addtransition(this, &controller::taskrunning, &s_busy); s_busy.addtransition(this, &controller::alltasksdone, &s_idle); m_machine.setinitialstate(&s_init); m_machine.start(); // connect(this, &controller::task1done, this, [this](int result){ ontaskdone(); qdebug() << "task 1 done result" << result; }); connect(this, &controller::task2done, this, [this](int result){ ontaskdone(); qdebug() << "task 2 done result" << result; }); connect(&s_busy, &qstate::entered, this, &controller::active); connect(&s_idle, &qstate::entered, this, &controller::finished); } }; q_global_static(qstringlistmodel, model) int main(int argc, char ** argv) { using q = qobject; qapplication app{argc, argv}; controller ctl; qwidget w; qformlayout layout{&w}; qpushbutton start1{"start task 1"}; qpushbutton start2{"start task 2"}; qlistview log; layout.addrow(&start1); layout.addrow(&start2); layout.addrow(&log); q::connect(&start1, &qpushbutton::clicked, &ctl, &controller::dotask1); q::connect(&start2, &qpushbutton::clicked, &ctl, &controller::dotask2); q::connect(&ctl, &controller::active, []{ qdebug() << "active"; }); q::connect(&ctl, &controller::finished, []{ qdebug() << "finished"; }); log.setmodel(model); qinstallmessagehandler(+[](qtmsgtype, const qmessagelogcontext &, const qstring & msg){ auto row = model->rowcount(); model->insertrow(row); model->setdata(model->index(row), msg); }); w.show(); return app.exec(); } #include "main.moc"
Comments
Post a Comment