views:

1090

answers:

3

I am not calling exec() yet my timer and QUdpSocket work just fine. Is exec used to wait for an event to continue?

+2  A: 

Your timer and socket are probably using the main event loop that is started when you call QCoreApplication::exec(). Although I'm sure there's a good reason to run an event loop within a thread, I can't come up with one.

The QThread documentation states:

Each QThread can have its own event loop. You can start the event loop by calling exec(); you can stop it by calling exit() or quit(). Having an event loop in a thread makes it possible to connect signals from other threads to slots in this thread, using a mechanism called queued connections. It also makes it possible to use classes that require the event loop, such as QTimer and QTcpSocket, in the thread. Note, however, that it is not possible to use any widget classes in the thread.

Without an event loop, it's possible to emit signals which are processed by the GUI thread, or a different thread containing an event loop. This implies that a thread must have an event loop in order for its slots to be effectual. Per the documentation above, some classes, like QTimer, require a running event loop for which you must call QThread::exec(). Other classes, like QTCPSocket have capabilities to run with with or without an event loop, depending on the functions used. The documentation for the classes should indicate what, if any, requirements they have.

Kaleb Pederson
one I could think is when instantiating a QThread in main.cpp ie out of a QMainWindow.
yan bellavance
The main reason is if you have multiple threads or multiple objects in a non-GUI thread. This way the slots and signals of those objects can be triggered and executed without slowing down the GUI event loop.
Adam W
Post edited and clarifications added.
Kaleb Pederson
+1  A: 

In order to actually use your thread, instead of the QApplication execution loop, you have to call moveToThread(this) within the thread constructor AND place an execution loop within the protected run() method of your QThread derived class.

Seperate threads execution loop prevents the QApplication loop getting cluttered with non-ui related signals and slots, and therefore delaying for .e.g button click's slot execution, making your application "lag".

Note: Normally you always subclass QThread, see Qt doc for more information

penguinpower
what do you mean by "place an execution loop" do you mean calling QThread.exec() or actually instantiating a QEvent loop (though I would not see why I would need to do this since QThread provides one but from the waythe answer is written it makes me think of that)
yan bellavance
event loop is anything that does exec() and blocks code _after_ that class.exec() statement.In this case it is meant to be QThread.exec().Note: If your signal frequency is low, you could just drop the idea of threads, as most part of time consuming Qt commands are async.
penguinpower
so lets say I have a timer. Now if I want my timer to work I need to call exec. but what if I need to do processing in a loop in my run method, I would need to call exec once every loop? What if the timer is not even close to being done and I want to do the most processing possible while the timer times out. I read somewhere using a timer with 0 timeout is usefull to manage the eventloop.
yan bellavance
"processing in a loop" I don't get your point.And should NEVER call exec() multiple times within any thread, that's uggly coding style.If you really need all your processing power, but still process signals/slots:forever{processEvents(); //atm I can't remind how that qt function is calledextrem_cpu_intense_task(args);msleep(ms); //give some ms breating time};Note: this is only for seperate QThread derived classes, _NEVER_ do this for the UI and only if you really require _massive_ cpu power AND a high frequency of signal/slot emission/execution.
penguinpower
there are 2 functions in QUdpSocket (actually QAbstractSocket) called waitForReadyRead() and waitForBytesWriten(). this shows that it is possible to have processing done without the use of signal. Of course you cant use those if your QThread is not separate from gui thread, it generates a double free exception. In the mandlebrot example the run() contains a forever{} loop.
yan bellavance
about moveToThread, do I absolutly need to call this in the constructor or can I call it later on?
yan bellavance
There was a discussion about that on qtcentre.org and the result was ( I am not up to date with that posting thread anymore), that you need to call moveToThread(this) _before_ you actually start the thread via threadName.start().http://www.qtcentre.org/threads/21712-moveToThread()-Problem
penguinpower
A: 

It depend on your programs. Here is an example:

void MyThread::run(){
  Curl * curl = new Curl();
  connect( curl, SIGNAL(OnTransfer(QString)), this, SLOTS(OnTransfer(QString)) );
  connect( curl, SIGNAL(OnDone()), curl, SLOTS(deleteLater()) );
  curl->Download("http://google.com");
  exec(); // this is an event loop in this thread, it will wait until you command quit()
}

void MyThread::OnTransfer(QString data){
  qDebug() << data;
}

Without exec(), OnTransfer will never be called. BUT if your create curl outside run with this (assume MyThread parent is main thread) as parent :

MyThread::MyThread(){
  curl = new Curl(this);
  connect( curl, SIGNAL(OnTransfer(QString)), this, SLOTS(OnTransfer(QString)) );
  start();
}
void MyThread::run(){
  curl->Download("http://google.com");
}

This one will work as you expected. OnTransfer will be called.

Rozi