1

Suppose I have a class cWorker : public QObject that contains a SLOT listen(). This object is moved to a separate thread.

The main window contains a class GLWidget : public QGLWidget, that has a SIGNAL request()

How do I connect the signal-slot across the two threads? It should be straight forward but I could not find any example code on that. Thanks.

int main(int argc, char *argv[])
{

cWorker* worker = new cWorker();

QThread* thread = new QThread;
worker->moveToThread(thread);

QObject::connect(thread, SIGNAL(started()), worker, SLOT(work()) );

thread->start();


QApplication a(argc, argv);
MainWindow w;

GLWidget *my_gl_widget = w.findChild<GLWidget*>("widget");


// THIS DOESN'T WORK
QObject::connect(my_gl_widget, SIGNAL( request() ), worker, SLOT( listen() ));


w.show();

return a.exec();

}

user2926577
  • 1,717
  • 4
  • 14
  • 16

1 Answers1

6

When you connect two QObjects in different threads, Qt always uses QueuedConnection. It means that when a signal is emited Qt sends an event to another object. More info.

The problem is that Qt can't deliver the event until you exit the loop.

To be able to process events you need to a) break your infinite loop in cWorker::work or b) call processEvents there.

a) To break a loop you can use QTimer. So instead of:

while (true) do something;

You will have:

void onTimer()
{
 do something()
}

b) If you need to perform a persistent operation there (calculation, etc.) you can use QCoreApplication::processEvents.

Here is a description of processEvents from the documentation:

Processes pending events for the calling thread for maxtime milliseconds or until there are no more events to process, whichever is shorter. You can call this function occasionally when you program is busy doing a long operation (e.g. copying a file).

Conclusion:
The infinite loop is the reason of your issue. You can ensure in that: if you remove this row the slot listen will be invoked:

QObject::connect(thread, SIGNAL(started()), worker, SLOT(work()) );

Community
  • 1
  • 1
Ezee
  • 4,214
  • 1
  • 14
  • 29
  • Indeed. Thanks. Here is my problem: I am running the main thread to render the glwindow at max 60Hz and the worker thread at 1kHz. The worker thread contains the vertex data and continuously operations on it. The vertex data is needed in paintGL(). What's the best method to copy/pass the vertex data from the worker to the main thread whenever paintGL() is called? I thought that a signal-slot mechanism would be best, but that doesn't seem to be the case now? – user2926577 Oct 23 '14 at 06:48
  • Just to make sure I understand correctly: I should put `processEvents ` in my infinite while-loop? What happens if copying the vertex data takes longer than `maxtime`? It seems like there should be a better method to exchange data between threads that run continuously.. – user2926577 Oct 23 '14 at 07:12
  • In most cases you need to use signal-slot only if you send small pieces of data or time of delivering is not crusial. But if it works for you then yes, you only need to add `processEvents` to the loop. Use another overloaded method `processEvents` which doesn't require `maxtime`. – Ezee Oct 23 '14 at 07:20
  • I would also think about sharing data and `QMutex`. Also you may want to read http://qt-project.org/forums/viewthread/6276 and http://qt-project.org/forums/viewthread/31125 – Ezee Oct 23 '14 at 07:21