Thread is surely one of the most discussed topic on Qt forums. Meanwhile, I never managed to find a simple example which describes how to simply do what I want to do: run a thread to do things and interrupt it if necessary (for example if the GUI is closed). That's why I'm writing this post (in fact, that's even why I started this blog…). I hope this will save some time to those who don't want to spent time on docs and forums, looking for the multiple pieces needed to bring together this solution.
Qt Connect Signal Slot Thread only sort them by the software developers. Also, you should note that there is a search Qt Connect Signal Slot Thread function which you can use to locate specific games. Some notable roulette games which you can play on the platform are Lightning Roulette, Immersive Roulette, Auto Roulette, and Speed Roulette Live. Queued Connection The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread. Blocking Queued Connection The slot is invoked as for the Queued Connection, except the current thread blocks until the slot returns. The slots are executed in the thread context that emitted the signal. Warning: Slots that generate window system events or use window system functions must not be connected to a signal that is emitted from a thread that is not the GUI thread. See the Qt Library Mutex section above for more details. Threads and Shared Data.
Here is the problem I want to solve in this example:
- Create a main thread with GUI
- Start another thread which will do things (counts 60 sec in this example, but it could do whatever you want) and properly closes itself when it is done
- When the GUI is closed, if the other thread is running, it will force it to abort and then will wait for it to finish as soon as possible
A fully working project with all sources is available for this example on GitHub: https://github.com/fabienpn/simple-qt-thread-example
So, how does it work. First, we need a class which will do the work we want in a separate thread. In this example, this class is called Worker and will do its work in the function doWork(). The doWork() function simply waits 1 sec then increments a counter. This approach is the new 'good' approach, compared to the old way of doing it: subclassing QThread. This excellent post explains why subclassing QThread is not relevant anymore since Qt 4.4: You're doing it wrong…
As we want to display the counter value on the GUI, we add a signal valueChanged() which will be emitted every time the value changed (!).
Now is the interesting part as we need a little more fabric to make this class fully usable in a threading context. First we need a finished() signal. This signal will be emitted when the work is finished to inform the thread that it should stop. Then we need an _abort boolean. When this boolean is set to true the counter loop will stop and the doWork() function will finished. So, basically, all the main thread will have to do to stop the worker is to set _abort to true. We also set a _working boolean to false at the end of the function. This boolean will be checked to define if the Worker is working and thus, if it can be aborted. But things aren't that simple as accessing a variable from both threads can be dangerous. That's why a QMutex will be used to protect accesses to _abort and _working (I'm not 100% sure it is needed as read/write accesses might be atomic but it's always a better practice to protect variables between threads). By the way, this part of the code contains a method to 'wait' using a QTimer. This is also a topic which I've seen frequently on Qt forums.
The function requestWork() is called to inform that we want the thread to start. It will set _working to true and _abort to false to allow the thread to be interrupted from now on.
The function abort() will simply check if the Worker is working and set _abort to true while protecting it. This method of thread interruption is inspired by the Qt Mandelbrot example.
To ensure that the thread won't be aborted on its first run, _abort and _working are set to false in class constructor. There is no need to protect variables with mutex here because the Worker is still in the main thread when it is created thus there can't be concurrent access to variables.
And here is how the Worker class looks like :
Now the main GUI class. One of the most important rule in Qt threading is that all threads must be stopped before the main thread is exited. That's why we have to wait for the worker thread to finish in the destructor. But the thread won't stop unless the counter finished or is interrupted. So we have to manually abort the counter in the destructor then wait for the thread to finish. That's why we need pointers to both, the thread and the worker in the GUI class.
The constructor will instantiate both the Worker and the QThread. Then, the worker is moved to the thread. That will give ownership of this worker to the other thread which will be able to freely manipulate it. Then we connect the Worker::valueChanged() signal to update display. The important part comes after. The workRequested() signal of the Worker is connected to the start() function of the thread which means that the thread will start when requestWork() is called. The started() signal of the thread is connected to the doWork() function of the worker which means that as soon as the thread starts, the doWork() function is called. Then we connect the finished() signal of the worker to the quit() slot of the thread, ensuring that the thread will stop when the work is done. This connection needs to be direct to ensure not being blocked waiting for the thread to exit (with the event enqueued and never processed). This method has been inspired by the excellent post by Maya on this subject: How To Really, Truly Use QThreads; The Full Explanation.
To start the work in a different thread, we just need to call worker->requestWork() but before calling it, we need to ensure that it is not running. The wait() function is what we need for that. It will wait until the thread finishes and then returns. To ensure we don't wait the whole 60 secs and finish the work as soon as possible, we call abort() on the worker before:
In the destructor, we finish the thread the same way, then delete the objects
And that's it. With this method, it is really easy to make 'one call' and permanent threads running in a very stable way and without headache. Again, feel free to take a look at the full source code on GitHub and comment on this post if you have question or want to improve this method. I hope this will save some time to some.
Fabien
Qt Slot In Different Thread
UPDATE: In that post, it is explained how to have a thread running forever and waiting for requests of various methods. You can head there if you're interested in this case.
Qt Slot Thread
EDIT: Thanks to Sandeep, a problem has been solved. In first version, abort() function didn't check if work was requested but only if thread was running. It was then possible to request abortion after work request was done but before thread starting, resulting in abortion not being taken into account. That is why the requestWork() has been introduced so work request is done in same thread as abortion request.
Posted in Qt
Example
Some times you see a signal is emitted in sender thread but connected slot doesn't called (in other words it doesn't receive signal), you have asked about it and finaly got that the connection type Qt::DirectConnection would fix it, so the problem found and everything is ok.
Qt Signal Slot Thread Context
But generaly this is bad idea to use Qt:DirectConnection until you really know what is this and there is no other way. Lets explain it more, Each thread created by Qt (including main thread and new threads created by QThread) have Event loop, the event loop is responsible for receiving signals and call aproporiate slots in its thread. Generaly executing a blocking operation inside an slot is bad practice, because it blocks the event loop of that threads so no other slots would be called.
- Qt Slot In Different Thread
- Qt Slot Thread
- Qt Signal Slot Thread Context
- Qt Slot Thread Tool
- Qt Run Slot In Thread
Thread is surely one of the most discussed topic on Qt forums. Meanwhile, I never managed to find a simple example which describes how to simply do what I want to do: run a thread to do things and interrupt it if necessary (for example if the GUI is closed). That's why I'm writing this post (in fact, that's even why I started this blog…). I hope this will save some time to those who don't want to spent time on docs and forums, looking for the multiple pieces needed to bring together this solution.
Qt Connect Signal Slot Thread only sort them by the software developers. Also, you should note that there is a search Qt Connect Signal Slot Thread function which you can use to locate specific games. Some notable roulette games which you can play on the platform are Lightning Roulette, Immersive Roulette, Auto Roulette, and Speed Roulette Live. Queued Connection The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread. Blocking Queued Connection The slot is invoked as for the Queued Connection, except the current thread blocks until the slot returns. The slots are executed in the thread context that emitted the signal. Warning: Slots that generate window system events or use window system functions must not be connected to a signal that is emitted from a thread that is not the GUI thread. See the Qt Library Mutex section above for more details. Threads and Shared Data.
Here is the problem I want to solve in this example:
- Create a main thread with GUI
- Start another thread which will do things (counts 60 sec in this example, but it could do whatever you want) and properly closes itself when it is done
- When the GUI is closed, if the other thread is running, it will force it to abort and then will wait for it to finish as soon as possible
A fully working project with all sources is available for this example on GitHub: https://github.com/fabienpn/simple-qt-thread-example
So, how does it work. First, we need a class which will do the work we want in a separate thread. In this example, this class is called Worker and will do its work in the function doWork(). The doWork() function simply waits 1 sec then increments a counter. This approach is the new 'good' approach, compared to the old way of doing it: subclassing QThread. This excellent post explains why subclassing QThread is not relevant anymore since Qt 4.4: You're doing it wrong…
As we want to display the counter value on the GUI, we add a signal valueChanged() which will be emitted every time the value changed (!).
Now is the interesting part as we need a little more fabric to make this class fully usable in a threading context. First we need a finished() signal. This signal will be emitted when the work is finished to inform the thread that it should stop. Then we need an _abort boolean. When this boolean is set to true the counter loop will stop and the doWork() function will finished. So, basically, all the main thread will have to do to stop the worker is to set _abort to true. We also set a _working boolean to false at the end of the function. This boolean will be checked to define if the Worker is working and thus, if it can be aborted. But things aren't that simple as accessing a variable from both threads can be dangerous. That's why a QMutex will be used to protect accesses to _abort and _working (I'm not 100% sure it is needed as read/write accesses might be atomic but it's always a better practice to protect variables between threads). By the way, this part of the code contains a method to 'wait' using a QTimer. This is also a topic which I've seen frequently on Qt forums.
The function requestWork() is called to inform that we want the thread to start. It will set _working to true and _abort to false to allow the thread to be interrupted from now on.
The function abort() will simply check if the Worker is working and set _abort to true while protecting it. This method of thread interruption is inspired by the Qt Mandelbrot example.
To ensure that the thread won't be aborted on its first run, _abort and _working are set to false in class constructor. There is no need to protect variables with mutex here because the Worker is still in the main thread when it is created thus there can't be concurrent access to variables.
And here is how the Worker class looks like :
Now the main GUI class. One of the most important rule in Qt threading is that all threads must be stopped before the main thread is exited. That's why we have to wait for the worker thread to finish in the destructor. But the thread won't stop unless the counter finished or is interrupted. So we have to manually abort the counter in the destructor then wait for the thread to finish. That's why we need pointers to both, the thread and the worker in the GUI class.
The constructor will instantiate both the Worker and the QThread. Then, the worker is moved to the thread. That will give ownership of this worker to the other thread which will be able to freely manipulate it. Then we connect the Worker::valueChanged() signal to update display. The important part comes after. The workRequested() signal of the Worker is connected to the start() function of the thread which means that the thread will start when requestWork() is called. The started() signal of the thread is connected to the doWork() function of the worker which means that as soon as the thread starts, the doWork() function is called. Then we connect the finished() signal of the worker to the quit() slot of the thread, ensuring that the thread will stop when the work is done. This connection needs to be direct to ensure not being blocked waiting for the thread to exit (with the event enqueued and never processed). This method has been inspired by the excellent post by Maya on this subject: How To Really, Truly Use QThreads; The Full Explanation.
To start the work in a different thread, we just need to call worker->requestWork() but before calling it, we need to ensure that it is not running. The wait() function is what we need for that. It will wait until the thread finishes and then returns. To ensure we don't wait the whole 60 secs and finish the work as soon as possible, we call abort() on the worker before:
In the destructor, we finish the thread the same way, then delete the objects
And that's it. With this method, it is really easy to make 'one call' and permanent threads running in a very stable way and without headache. Again, feel free to take a look at the full source code on GitHub and comment on this post if you have question or want to improve this method. I hope this will save some time to some.
Fabien
Qt Slot In Different Thread
UPDATE: In that post, it is explained how to have a thread running forever and waiting for requests of various methods. You can head there if you're interested in this case.
Qt Slot Thread
EDIT: Thanks to Sandeep, a problem has been solved. In first version, abort() function didn't check if work was requested but only if thread was running. It was then possible to request abortion after work request was done but before thread starting, resulting in abortion not being taken into account. That is why the requestWork() has been introduced so work request is done in same thread as abortion request.
Posted in Qt
Example
Some times you see a signal is emitted in sender thread but connected slot doesn't called (in other words it doesn't receive signal), you have asked about it and finaly got that the connection type Qt::DirectConnection would fix it, so the problem found and everything is ok.
Qt Signal Slot Thread Context
But generaly this is bad idea to use Qt:DirectConnection until you really know what is this and there is no other way. Lets explain it more, Each thread created by Qt (including main thread and new threads created by QThread) have Event loop, the event loop is responsible for receiving signals and call aproporiate slots in its thread. Generaly executing a blocking operation inside an slot is bad practice, because it blocks the event loop of that threads so no other slots would be called.
If you block an event loop (by making very time consuming or blocking operation) you will not receive events on that thread until the event loop will be unblocked. If the blocking operation, blocks the event loop forever (such as busy while), the slots could never be called.
Qt Slot Thread Tool
In this situation you may set the connection type in connect to Qt::DirectConnection, now the slots will be called even the event loop is blocked. so how this could make broke everything? In Qt::DirectConnection Slots will be called in emiter threads, and not receiver threads and it can broke data synchronizations and ran into other problems. So never use Qt::DirectConnection unless you know what are you doing. If your problem will be solved by using Qt::DirectConnection, you have to carefull and look at your code and finding out why your event loop is blocked. Its not a good idea to block the event loop and its not recomended in Qt.
Here is small example which shows the problem, as you can see the nonBlockingSlot would be called even the blockingSlot blocked event loop with while(1) which indicates bad coding