c++ - Qt connection type between threads: why does this work? -


while trying make multi-camera system work different thread handling different camera, couldn't signals , slots working correctly between different threads. knew wrong fact object sending signal , related slot's object living in different threads, , knew had find appropriate "connection type" parameter connection. eventually, ended discovering using qt::directconnection make work should.

find simplified code below. here's small description of how should work.

  • application main program supposed create threads , start them. in simplified version, waits worker finish jobs through slot "quit".

  • worker object performs 1 of threaded tasks. in simplified example, wait time before finishing computation. worker emits signal directed application instance, allowed wait threads , quit qcoreapplication.

what finding if don't use qt::directconnection in second connect, finished() signal of worker not trigger quit() slot of thread, means application remains hanging waiting thread.

my question is: why so? since 2 objects (the worker , thread) belong different threads, shouldn't using queuedconnection, or else? thought directconnection should used objects belonging same thread.

main.cpp:

#include <iostream> #include <qcoreapplication> #include "program.h"  using namespace std;  int main(int argc, char **argv) {   qcoreapplication app(argc, argv);    program *p = new program;   p->execute();    app.exec();    delete p; } 

program.h

#ifndef _program_h_ #define _program_h_  #include <qthread> #include <qtimer> #include "worker.h"  class program: public qobject {   q_object    private:     worker *worker;     qthread *thread;    public:     void execute();    public slots:     void quit(); };  #endif // _program_h_ 

program.cpp

#include "worker.h"  using namespace std;  void program::execute() {   worker = new worker();   thread = new qthread;   worker->movetothread(thread);    cout << "connection established: "         << connect(thread, signal(started()), worker, slot(process()))         << endl;    // slot not called if remove fifth parameter   // or if put qt::queuedconnection   cout << "connection established: "         << connect(worker, signal(finished()), thread, slot(quit()),                     qt::directconnection)         << endl;    cout << "connection established: "         << connect(worker, signal(finished()), this, slot(quit()))         << endl;    cout << "connection established: "         << connect(worker, signal(finished()), worker, slot(deletelater()))         << endl;    cout << "connection established: "         << connect(worker, signal(finished()), thread, slot(deletelater()))         << endl;    thread->start(); }  void program::quit() {   cout << "waiting.." << endl;   thread->wait();   cout << "           .. i'm done!" << endl;    cout << "quitting all.." << endl;   qcoreapplication::quit();   cout << "           .. i'm done!" << endl; }  #include "program_moc.cpp" 

worker.h

#ifndef _worker_h_ #define _worker_h_  #include <qobject>  class worker: public qobject {   q_object    public slots:     void process();    signals:     void finished(); };  #endif // _worker_h_ 

worker.cpp:

#include <iostream> #include <unistd.h> #include "worker.h"  using namespace std;  void worker::process() {   cout << "worker::process() started" << endl;   usleep(1000000);    cout << "worker::finished() being emitted" << endl;   emit finished();    cout << "worker::process() finished" << endl; }  #include "worker_moc.cpp" 

edit

following @ariwez 's answer solve problem in specific simplified example, doesn't in more complex one, adding now.

in example,

  • program has own job execute periodically through use of qtimer. program has yet qtimer used simulate user quitting program, triggers execution of slot program::quit().

  • worker executes own job until quitting flag gets set false. done inside program::quit().

as in previous example, worker finishes procedure , emits finished() signal, supposed connected thread's quit() slot. however, somehow slot must not executed, because program hangs waiting thread. differently previous example, relocating movetothread procedure not solve issue: works if , if use qt::directconnection type connection between worker::finished() , qthread::quit(), , can't understand why.

main.cpp: same above

program.h:

#ifndef _program_h_ #define _program_h_  #include <qthread> #include <qtimer> #include "worker.h"  class program: public qobject {   q_object    private:     qtimer *timer, *quittingtimer;     worker *worker;     qthread *thread;    public:     ~program();      void execute();    private slots:     void quit();     void update(); };  #endif // _program_h_ 

program.cpp:

#include <iostream> #include <qcoreapplication> #include "program.h" #include "worker.h"  using namespace std;  program::~program() {   delete timer;   delete quittingtimer; }  void program::execute() {   timer = new qtimer();   timer->setinterval(500);   connect(timer, signal(timeout()), this, slot(update()));    worker = new worker;   thread = new qthread;    cout << "connection established: "         << connect(thread, signal(started()), worker, slot(process()))         << endl;    // doesn't work if remove qt::directconnection   cout << "connection established: "         << connect(worker, signal(finished()), thread, slot(quit()),                     qt::directconnection)         << endl;    cout << "connection established: "         << connect(worker, signal(finished()), this, slot(quit()))         << endl;    cout << "connection established: "         << connect(worker, signal(finished()), worker, slot(deletelater()))         << endl;    cout << "connection established: "         << connect(worker, signal(finished()), thread, slot(deletelater()))         << endl;    worker->movetothread(thread);    timer->start();   thread->start();    // simulates user pressing key close program   quittingtimer = new qtimer();   quittingtimer->singleshot(4000, this, slot(quit())); }  void program::quit() {   cout << "timer->stop()" << endl;   timer->stop();    cout << "worker->quit()" << endl;   worker->quit();    cout << "thread->wait()" << endl;   thread->wait();    cout << "qcore->quit()" << endl;   qcoreapplication::quit(); }  void program::update() {   cout << "program::update() called" << endl; }  #include "program_moc.cpp" 

worker.h:

#ifndef _worker_h_ #define _worker_h_  #include <qobject>  class worker: public qobject {   q_object   private:     bool quit_flag;    public:     void quit();    public slots:     void process();    signals:     void finished(); };  #endif // _worker_h_ 

worker.cpp:

#include <iostream> #include <unistd.h> #include <qthread> #include "worker.h"  using namespace std;  void worker::quit() {   quit_flag = true; }  void worker::process() {   quit_flag = false;   while(!quit_flag) {     cout << "worker::process() processing" << endl;     usleep(300000);   }   cout << "worker::finished() being sent" << endl;   emit finished();   cout << "worker::finished() sent" << endl; }  #include "worker_moc.cpp" 

edit 2

re-reading article in @ariwez 's link found out problem in second example. problem main event loop being interrupted, while waiting thread's qthread::finished() signal, , worker::finished() signal not dispatched qthread::quit() slot. yeah, deadlocked myself.

you movetothread before connects that's why in 1 thread.


Comments

Popular posts from this blog

image - ClassNotFoundException when add a prebuilt apk into system.img in android -

I need to import mysql 5.1 to 5.5? -

Java, Hibernate, MySQL - store UTC date-time -