After an admittably brief hiatus the Qt Commercial Support weekly post is back in full swing for the new year! To start off for the new year I will be covering threads and how they tend to get misused generally which can lead to problems later on. This may be not be new information to a fair number if not the majority of you but it isn’t entirely uncommon that people get tripped up on these things.
Problem #1: Putting slots inside the thread subclass and using them from objects inside the run() function.
It is an easy mistake to make as you already need to subclass QThread in order to be able to reimplement run() which is where all the code to be executed in the other thread should go. But if you are adding slots as members of the QThread subclass then they will exist in a different affinity to the thread you are using. When run() is invoked then it is inside another thread and any objects created in there belong to that thread. Whereas the QThread object itself belongs to the thread that it was actually created in which is typically the main thread.
Therefore if you want to ensure the slots are invoked in the right thread then you should subclass QObject and add the slots as members to that subclass and create an instance of the QObject subclass inside the run() function. This will ensure they exist in the same thread then.
Problem #2: Creating an object inside the thread’s run() function and passing ‘this’ as the parent.
It is a natural thing to do as we are used to passing in this when creating a widget or object so that we don’t need to worry about the parent-child hierarchy and cleaning up after ourselves. However, this causes a problem within the other thread because in this context – ‘this’ is the QThread object which belongs to a different thread. In order to ensure there is still a parent-child relationship then you can still pass a parent, but it should be an object created/owned by the thread.
Problem #3: Causing an update on a widget inside the thread’s run() function.
This may seem obvious as something you shouldn’t be doing because it is documented as such in the Qt documentation but it does slip from people’s minds and sometimes this sort of thing can appear to work and subseqently get forgotten until later on. This can be something like triggering a change to a model or even setting a model on a view. In some cases it can be safe to prepare something before passing it on to the other thread, with moveToThread() and then doing the call that triggers the update in the main thread. But it is never safe to do it directly. It might work but it is likely to have problems later on.
So those are the three main problems to watch out for, there are some more things to watch out for which you can find in the documentation at http://doc.qt.nokia.com/threads.html.
Before I sign off for another week, I would like to request feedback from our customers out there, we do value any feedback we get from you be it for a particular case or for support in general. Especially if we send a patch to you because it helps us to know if the patch solves the problem or not, particularly if it introduces any problems as we can only test it in a limited context in support. Sometimes this feedback can mean that we can submit a patch safely back into Qt or it will go a long way to helping the developers solve the problem in the next release.