添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
> Multi-threading , programming , Qt > How To Really, Truly Use QThreads; The Full Explanation

How To Really, Truly Use QThreads; The Full Explanation

November 1, 2011 Leave a comment Go to comments

Threads in an operating system are a very simple thing. Write a function, maybe bundle it with some data and push it onto a newly created thread. Use a mutex or other method to safely communicate with the thread if necessary. Whether it are Win32, POSIX or other threads, they all basically work the same and are quite fool-proof. I’d venture to say that they’re at least a lot easier to use and handle than sockets 🙂

Those who have discovered the joys of the Qt framework may assume that threads in Qt (QThread) are just like this, but they would be both wrong and right. Wrong because years of wrong documentation from Trolltech/Nokia on QThread has caused countless people to use QThreads in a convoluted and highly inappropriate manner. Right because QThreads are in fact quite easy to use, as long as you ignore the incorrect official Qt documentation on QThread [1] and the myriad of wrongful methods being employed.

The main thing to keep in mind when using a QThread is that it’s not a thread. It’s a wrapper around a thread object. This wrapper provides the signals, slots and methods to easily use the thread object within a Qt project. This should immediately show why the recommended way of using QThreads in the documentation, namely to sub-class it and implement your own run() function, is very wrong. A QThread should be used much like a regular thread instance: prepare an object (QObject) class with all your desired functionality in it. Then create a new QThread instance, push the QObject onto it using moveToThread(QThread*) of the QObject instance and call start() on the QThread instance. That’s all. You set up the proper signal/slot connections to make it quit properly and such, and that’s all.

For a basic example, check this class declaration for the Worker class:

class Worker : public QObject { Q_OBJECT public: Worker(); ~Worker(); public slots: void process(); signals: void finished(); void error(QString err); private: // add your variables here

We add at least one public slot which will be used to trigger the instance and make it start processing data once the thread has started. Now, let’s see what the implementation for this basic class looks like.

// --- CONSTRUCTOR --- Worker::Worker() { // you could copy data from constructor arguments to internal variables here. // --- DECONSTRUCTOR --- Worker::~Worker() { // free resources // --- PROCESS --- // Start processing data. void Worker::process() { // allocate resources using new here qDebug("Hello World!"); emit finished();

While this Worker class doesn’t do anything special, it nevertheless contains all the required elements. It starts processing when its main function, in this case process(), is called and when it is done it emits the signal finished() which will then be used to trigger the shutdown of the QThread instance it is contained in.

By the way, one extremely important thing to note here is that you should NEVER allocate heap objects (using new) in the constructor of the QObject class as this allocation is then performed on the main thread and not on the new QThread instance, meaning that the newly created object is then owned by the main thread and not the QThread instance. This will make your code fail to work. Instead, allocate such resources in the main function slot such as process() in this case as when that is called the object will be on the new thread instance and thus it will own the resource.

Now, let’s see how to use this new construction by creating a new Worker instance and putting it on a QThread instance:

QThread* thread = new QThread; Worker* worker = new Worker(); worker->moveToThread(thread); connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString))); connect(thread, SIGNAL(started()), worker, SLOT(process())); connect(worker, SIGNAL(finished()), thread, SLOT(quit())); connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater())); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->start();

The connect() series here is the most crucial part. The first connect() line hooks up the error message signal from the worker to an error processing function in the main thread. The second connects the thread’s started() signal to the processing() slot in the worker, causing it to start.

Then the clean-up: when the worker instance emits finished(), as we did in the example, it will signal the thread to quit, i.e. shut down. We then mark the worker instance using the same finished() signal for deletion. Finally, to prevent nasty crashes because the thread hasn’t fully shut down yet when it is deleted, we connect the finished() of the thread (not the worker!) to its own deleteLater() slot. This will cause the thread to be deleted only after it has fully shut down.

I hope this small tutorial is of some use to people out there. It has taken me months to put together this method of doing things involving countless frustrating hours of debugging and Google searches which kept repeating the same wrong mantra of ‘sub-class QThread’. Constructive feedback on this tutorial is much appreciated. Emails to Nokia on the wrong QThreads documentation might be a good idea too as I would love for the myths surrounding QThread to finally be erased from this world 🙂

[1] http://doc.trolltech.com/4.7/qthread.html

A lot of the reasoning behind the (mis)use of QThread in the Qt documentation is, I believe, left over from the way things were done in Qt 3. I could be wrong. As one of the perpetrators of the “wrong” way of doing things, I wish there could be a better discussion of both approaches in the documentation because it seems to me that each approach has its merits.

Hopefully, the Qt Project effort will help get updates on subjects like these into the regular documentation, though this ultimately depends on having enough people with commit rights and available time to review and merge them into the mainline Qt tree. If you’re the sort of person who’s motivated to do that then I’d urge you to get involved in the project, or perhaps even to get hired as a writer:

http://qt.nokia.com/about/careers/technical-writer-in-oslo-norway

Disclaimer: I worked there until earlier this year.

Hi David 🙂

Yeah, the origins of such ‘sinful’ approaches to using QThreads are probably lost in history and all we can do now is to try and clean up the resulting mess.

At this point I do not really have the time to work on the Qt project unless I got hired by them 🙂 Maybe you could forward my CV to them together with the link to this blog and see what they think? 😉

I have one little worry here, which is a technical detail easilly overlooked.
I know that deleteLater works by creating an event on the objects event loop, which will delete it when the event queue gets to it. The quit on the thread is implemented in the same way, an event on the queue. And in this case its the same queue.
So my worry is that the quit is executed before the deleteLater is executed and we have a leak.

One easy solution might be that you don’t connect the finished() to the threads quit(), instead you connect the workers destroyed() to the threads quit().

One more thing that might be useful to add here is how to properly delete stuff if the user wants the app to quit before the finished() is emitted. I.e. how to delete the thread properly.
This typically means that someone in the gui thread calls quit() and then wait() on the thread object.

Thanks for the blog, excellent summary and overview. Love it 🙂

Hi Thomas,

The intention is for quit() to be executed before deleteLater(). As a serial queue is used there should be no issue here. As for the rest of your worries, do you mean connecting the finished() signal to deleteLater(), and instead connecting the thread’s terminated() signal upon terminating (as a result of quit()) to deleteLater()? That might work, but I haven’t tried it nor do I know whether it has any benefits.

This also ties in with calling quit() on the thread directly. There’s no real need to dispose of the thread and wait for its exit unless you’re dealing with a program termination.

Ah, I see my mistake; I’ve not explained which deleteLater() I’m talking about 🙂
I think the issue is still there, and my explanation is easy to misread, and I see you commented on something slightly different. Mind if I try again?

What this starts with is that there are two connects with the SLOT(deleteLater()) in them. Those two connects are handled by two different event queues. The first is on the worker object and due to its moveToThread its handled in the event queue of the ‘thread’ object.
The second is handled by the main QApplication event queue.

The worry I’m having is that this is happening;
* worker emits finished(). This causes 1) a new ‘please-quit’ event to be placed on the threads event queue. 2) a new ‘delete worker’ event to be placed on the threads event queue. 3) a new ‘delete thread’ event to be placed on the main-gui event loop.

The correct order of execution here is ‘delete worker’, ‘exit thread event-loop’ and last ‘delete thread’.
In Qt docs I’ve seen often mentioned that the order in which slots are executed is not deterministic. So my numbering of 1,2,3 is not a well-defined order.
Then there is the fact that this is spread over two threads and the order can be changed due to that too.

So, in short, I worry that due to event ordering not being enforced we might leak the ‘worker’ object.

I think I get thomaszander’s concern, for I share it. Let me try to put it this way.

In the example code line:
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));

This posts an event into the worker thread’s queue to delete the qthread object, when the qthread has finished. But if the thread truly has finished, it doesn’t have an event loop no more, doesn’t consume the deleteLater event, and thus, don’t get deleted.

My assumption is, that due to a race condition [1] inside the QThreadPrivate::finish, the code works however. It works at least in Qt 4.7, but it might not work in the future versions of QThread. If I understood it correctly, qhtread::finished() signal is emitted on the thread’s context (direct call to qhtreadprivate::finish), so in fact, the qthread is not finished when finished() is emitted. Issue is discussed here:

http://lists.qt-project.org/pipermail/development/2011-November/000284.html [1]

I have looked at my original approach and the one suggested by thomaszander. Without in-depth knowledge it’s hard to impossible to say which approach is more correct. At this point I’m inclined to go with the original approach as described due to it ‘feeling better’.

I guess someone has to dig through the source of QThread and related some day to answer this question definitely 🙂

i got directed to your blog from a link in an answer on QThreads for the question i posted on stackoverflow.com…ever since i read this article i’v been careful enough to design apps using the guidelines given here making use of moveToThread()…but in a recent case i’v got stuck a little…what if i don’t want a complete GUI app in the sense that there is no main GUI event loop…for instance say i just need the facilities of QFileDialog class which will be modal anyway and will be processed without requiring an event loop…i accept 2 files to process them in a similar fashion and this is time consuming…so i assign 2 files to two separate threads and make use of multicore processor to process them in parallel…the default version on run() in QThread is a mere exec() loop…in such a case how i can i avoid the re-implementation of this run() method? i cannot make connections since i’m not using any event loops…extending this, any app that does not make use of GUI event loops must subclass QThread…So am i missing on a better alternate design pattern here?

I am forever in your debt, Maya. It is really hard to understand why Qt does not properly document such an important matter. And a tricky one, your optimism notwithstanding.

If you could enlighten us a little further about thread-local data issues I’d be even more grateful. The Qt code around moveToThread() kind of looks to me like it is meant to transfer heap data to the new thread — but I don’t understand this at all well.

Then there is the little matter of terminating a thread synchronously and restarting it. Qt docs say QThread::wait() is equivalent to Unix join(). I have been using it where I want to stop and restart some loops that run in threads, and the results so far have been hung GUI thread and/or failure of the restarted loop. Have you an example of how to do this right?

Actually, you can fully use QThread by subclassing it.

After a few hours of poking around, a came up with this solution: http://engineer-dan.tumblr.com/post/36274332373/subclassing-qthread

Basically what I did was subclassed QThread, then called moveToThread(this) in the constructor.

@engineerdan – Sure, it’s possible to do it that way, but it’s technically speaking the most elegant. The main reason is essentially that you only sub-class when you absolutely have to. Sure, you can sub-class QThread, but with the same ease you can write a worker class instance and push it onto a regular QThread. Ergo it makes sense to only sub-class QThread when you absolutely need some kind of custom thread functionality not present in QThread.

hi Maya
great article, I’m struggling to get my simple example working though 😦 (sorry).
Can I ask some advice, I can’t see where I’m going wrong.
My main app constructor creates a thread; this thread just contains an infinite loop chucking out a signal every 10th of a second, the slot in also in my main app. This bit is very simple, not the problem (I think).
So the slot in my main app gets called 10 times a second and contains the code:

QThread* thrd = new QThread;
MyWorker* worker = new MyWorker();
worker->moveToThread(thrd);
connect(thrd, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), thrd, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thrd, SIGNAL(finished()), thrd, SLOT(deleteLater()));
connect(worker, SIGNAL(finished()), thrd, SLOT(deleteLater()));
thrd->start();

And the MyWorker class is almost identical to the code you have in your example. When it starts, it calls process() which is just:

void MyWorker::process()
emit finished();

If I run it in debug, after 10 seconds or so I get:

QEventDispatcherUNIXPrivate(): Unable to create thread pipe
Too many open files

It looks like its not deleting the threads 😦 Any ideas what I might be doing wrong?

many thanks

This might be related to the concerns some people had further up about the enqueuing of the `deleteLater` events. I’m trying to employ this method in Qt 4.8.3, but the code as presented in this example reproducibly leads to an access violation as soon as the QThread’s event loop gets around to consume the `deleteLater` event.

It seems that after executing the QThread’s `quit()` function, Qt is about to auto-delete the QThread object, but it is still in some sort of limbo state where the next event, `deleteLater`, is still consumed, to which it doesn’t take well. The same happens when trying to do a `delete thread;` after using `thread->quit(); thread->wait();`, the application will throw an access violation on the delete. I’m not sure if Qt actually garbage-collects these and I’m fine, or whether I’m leaking QThreads by omitting the delete/deleteLater; but if I am, I don’t know how to clean them up since any which way I try crashes my application. Considering it’s the `delete` itself that crashes seems to suggest it’s already been deleted though, right? (Unless the pointer was modified, which it wasn’t).

Daniel Saner :
This might be related to the concerns some people had further up about the enqueuing of the `deleteLater` events. I’m trying to employ this method in Qt 4.8.3, but the code as presented in this example reproducibly leads to an access violation as soon as the QThread’s event loop gets around to consume the `deleteLater` event.

After executing qthread::quit, your qthread exits it’s event loop, and should not be sent any (not even deleteLater events).

What if you, before exiting the qthread context – move you “qobject” back to main thread for deletion, where you still have a running event loop? After “processing”, call this->movetothread(qcoreapplication::instance()->thread()).

Daniel Saner :
It seems that after executing the QThread’s `quit()` function, Qt is about to auto-delete the QThread object, but it is still in some sort of limbo state where the next event, `deleteLater`, is still consumed, to which it doesn’t take well. The same happens when trying to do a `delete thread;` after using `thread->quit(); thread->wait();`, the application will throw an access violation on the delete. I’m not sure if Qt actually garbage-collects these and I’m fine, or whether I’m leaking QThreads by omitting the delete/deleteLater; but if I am, I don’t know how to clean them up since any which way I try crashes my application. Considering it’s the `delete` itself that crashes seems to suggest it’s already been deleted though, right? (Unless the pointer was modified, which it wasn’t).

I don’t think Qt garbage collects anything here – for these objects don’t have a parent. Qt only deletes a qobject’s children. In fact, in order for the qobject::movetothread to work, the object must not have parent (apparently to avoid this garbage collector to delete the object from another thread’s contect).

Thanks Maya, I have spent a good week trying to solve the very same problem using the sub-classing method discussed in my study material. It worked for a while and then suddenly I got dumps and unexpected failures in my code. After changing to the method discussed here and actualy finding that it is documented QT4.8 documentation, it started to work as expected.
“http://qt-project.org/doc/qt-4.8/qthread.html”

Using the combination of these two references I got the multithreaded applicaton to work without any issues.

I do have one question, I have long running threads and it seems like my application is then non responsive. I then tried calling the Qapplication::processEvents() method which I thaught would work simular to Microsofts doEvents() which should make the application responsive but it makes it only run longer.

The question is, where do have to add Qapplication::processEvents() or what is the most appropriate place to use this method.

Leaving elegance aside, what is the downside of subclassing Qthread like its done in the official documentation (e.g. Crashes? memory management? horrible shameful shutdowns?) I’m just learning Qt and as far as my experience goes the method works.

Reading the previous comments I see there are in fact problems with stability, but can you give an insight on why does this happens?

regarding the timing problem of the worker and thread on deleteLater():
As you explained, it is not guaranteed that the worker will be deleted in time. So my suggestion is to use the destroyed() signal emitted by the worker object:

connect(worker, SIGNAL(destroyed()), thread, SLOT(quit()));

Than there shouldn’t be any problem, or?

Hello Maya,
you mention that one should never allocate heap memory in the Object (probably referring to the worker. This may be easily achieve in some applications. My main application needs to allocate quite big resources (many GBs of RAM through NVIDIA mallocHost, mmap’d kernel memory, etc) at the very beginning which are shared across several threads performing work. If I used your approach, all my workers would still have to have references to objects created in the main thread, and of moveToThread of the workers will move themselves to the target thread, but not the objects they contain and work on. How would you go about that?
Cheers, peter.

Quote from above: “By the way, one extremely important thing to note here is that you should NEVER allocate heap objects (using new) in the constructor of the QObject class as this allocation is then performed on the main thread and not on the new QThread instance, meaning that the newly created object is then owned by the main thread and not the QThread instance. This will make your code fail to work. ”

IMHO the above statement is NOT true if we use a worker QObject and then moveToThread() properly and the heap objects are children of that worker QObject. Maybe the warning only applies to the case where people subclass QThread??? Please correct me if I’m wrong.

Following on from the posts above.. I’ve spent most of today trying to track down an illusive memory leak in a component i have written to push Pixmap images to a fileshare on its own thread. Turns out it was because of the concerns raised above with deleteLater, using Glowcode to profile my memory usage i found that something was holding a Shared memory reference to the pixmap after everything had been completed. I tracked this down to a QObject i was constructing and pushing onto a worker thread. Granted, it would work 95 out of 100 runs.. But the other 5%of the time the QObject would not be destroyed. I’ve adjusted to using:

connect(m_pMoveImageToFileShare, SIGNAL(destroyed()), m_pWorkerThread, SLOT(quit()), Qt::QueuedConnection);

And profiled it again everything is looking a lot better. So a note to anyone using this implementation, it works the vast majority of the time using the ‘finished’ signal from the object to the ‘quit’ slot on the worker thread but it is not bomb proof !

Using QThread is not necessary for a simple case of a simple worker class. The approach in this blog article still has a lot of overkill in it.

If you modify the Worker class above to the following:

class Worker : public QObject, public QRunnable{
Q_OBJECT

public:
Worker();
~Worker();

void run();

signals:
void finished();
void error(QString err);

private:
// add your variables here

(Note that the process slot from the blog example gets converted to the run virtual function)

Then you can use the power and convenience of QThreadPool and skip all the headaches that arise from managing the threads.

QThreadPool::globalInstance()->start(new Worker);

Hi Robert. Of course it might seem overkill in the article, but note that it’s about the correct use of QThread and not whether threads or the right solution to whatever problem one is faced with 🙂 Of course a QThreadPool and QRunnables would be more elegant in many cases, yet again this is not what this article is about. Cases where the use of a QThread is warranted is where one needs a lot of control over the creation, use and disposal of said thread. The Qt documentation also has an article on which type of concurrency to pick depending on the situation.

Quote: “you should NEVER allocate heap objects (using new) in the constructor of the QObject class as this allocation is then performed on the main thread and not on the new QThread instance, meaning that the newly created object is then owned by the main thread and not the QThread instance”.

I have never tried this but since threads are supposed to all share the same heap (they only have a distinct stack), I don’t see why it wouldn’t work. Please check your information.

Maybe threads have a distinct stack too in Qt but that would be very weird.

A great simple example Maya. I linked to it from a blog entry on my page, but I noticed something that could be of concern. As you know, a mutex must be used between threads sharing data. There is also the problem of sharing Qt implicitly shared objects between threads.

I can see that you pass a QString (implicitly shared) from the worker object to the main GUI thread using a signal and slot. While I haven’t looked into the exact implementation of this signal to slot process, I believe you will get a reference to the same QString at both threads. This means if you modify the QString in one thread while the other is using it, a crash may result. I say may result because it all depends on what code is being executed when the string is modified. The deep copy and reference atomic counting used in implicitly shared objects is not thread safe. It may only crash 1 in 1000 times, but those types of bugs are very hard to find and fix.

I covered this issue in this blog entry:

http://www.folding-hyperspace.com/real-time-programming-tips/tip-15-implicit-sharing-and.html

The example code I provide is somewhat flawed. I haven’t done much work on this because I simply avoid making this mistake and pass only safe non-shared objects on a signal to slot transaction. Perhaps some day I will do some more code testing to prove it is a problem.

Hello Maya,

Building an audio generator, for which I need a QThread – thanks very much for your coherent description of QThread usage.

Excellent.

John Russell (.au)

Hi. First paragraph, next to last sentence, grammar:

Whether it are Win32, POSIX or other threads

Suggest:

Whether it is Win32, POSIX or another thread type

Great post, btw

Hi Maya,

I copied your example code to my project.

When the thread finished its job, also main thread is exit with any error.

what is wrong here?

Code Below:

void MyServer::incomingConnection(int socketDescriptor)

QThread* thread = new QThread;

MyThread *UserSlot = new MyThread(socketDescriptor);

UserSlot->moveToThread(thread);
connect(thread,SIGNAL(started()),UserSlot,SLOT(StartTask()));
connect(UserSlot,SIGNAL(DisconnectSocket()),thread,SLOT(quit()));
connect(UserSlot,SIGNAL(DisconnectSocket()),UserSlot,SLOT(deleteLater()));
connect(thread,SIGNAL(finished()),thread,SLOT(deleteLater()));

thread->start();
ConnectedClientCount++;
con < Current Connection Count :”<<ConnectedClientCount;
Thanks for your great example code. I have tried your code its working fine in my linux mint but I got this error on windows 7: ASSERT failure in QCoreApplication::sendEvent: “Cannot send events to objects owned by a different thread. Current thread 1d856a78. Receiver ” (of type ‘DataMapperStokAwal’) was created in thread 1bc54568″, file kernel\qcoreapplication.cpp, line 514
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.
QObject::~QObject: Timers cannot be stopped from another thread

What should i do? this is the first time i use thread and database

Thanks

For quite some time I’ve been using QThread by subclassing and implementing the virtual run method in the subclass. With this solution the run method of the worker subclass is typically the main method (which is called “process” in the example) of the worker. The alternative of pushing a QObject from its instantiation context to a different QThread affinity (QObject::moveToThread), while an appropriate solution in many cases, also has its limitations. For example, when the application is not using QCoreApplication (or the QApplication subclass).

What is missing is an understanding of why a QObject worker process needs to be operating in the “correct” thread affinity context. It’s about the event loop used by the worker object. The base QObject class uses an event loop to manage deferred signal-slot deliveries and other events, and, being thread aware, will queue signal events on the event loop of the receiving slot object. Thus classes with signals and/or slots need a QObject which in turn needs an event loop that will convey the signal to slots (unless a DirectConnection is being used, in which case no event loop is used).

Thread affinity is about which thread will operate the OObject’s event loop.

By default a QObject uses the event loop operating in the thread in which it is instantiated. Every application obviously has at least the main thread. This is where the QApplication is (expected to be) instantiated, and where a GUI application’s main event loop operates when the its exec method is called. A QThread is a QObject subclass. The QThread is not instantiated in the thread that will be run when it is started, so the slots and signals of the QThread, and any objects it creates outside the context of its run method, will use the event loop operated by the thread where the QThread was instantiated. For QOjects created within the context of its run method signal and slots must be serviced by an event loop operated by the thread that was started for the run method. The default implementation of the QThread’s protected run method, which is called in QThread’s running thread context by its start method, will call its protected exec method that will operate the QThread event loop to manage slots and signals in the thread context. Implentations of a QThread subclass may call exec in their run method with the understanding that the method will not return until the QThread quit (or exit) method is called. This additional complexity can be avoided by setting the affinity of a QObject (moveToThread) to the desired QThread and using the default implmentation of the run method. Nevertheless, the additional complexity of subclassing QThread and providing a new run method offers significant additional control and sophistication for the operation of the thread process.

There are essentially two conceptual solutions for running a new thread: Simple and sophisticated. Choosing which to use will, of course, depend on what the implmentation intends to do. They are both the same behind the scenes.

Note that an application’s address space is shared by all threads of the application. An object (its data) can be accessed across threads. Problems arise when multiple threads attempt unsynchronized access to the same data, regardless of which object is accessed. The heap is an application resource which can be accessed from any thread as any other object. A thread may provide its own stack which, though it can be accessed across threads, is expected to be used for thread local automatic variables to help alieviate re-entrancy problems.

The documentation of Qt thread managment has been significantly enhanced to address many of the issues raised here (see http://doc.qt.io/qt-4.8/threads.html ). However, a thorough grasp of multi-threading requires more than reading the Qt documentation (;-).

I’m glad I found this post (and the StackOverflow link to it). Many thanks for clearing up the conflicting information I’ve found.

I’m a old hand at UI development so threads are nothing new, but I’m still a Qt n00b. I trust it’s all pretty much the same in Qt5?

This is all great stuff. I was wondering how one would go about exposing and utilizing this in QML or if that is even possible. I’d like to have an object running on a separate thread and be able to instantiate and connect to one of its signals in a QML object. Anyone have a code example of how that might work?

Dear,

First, I must say its a nice tutorial on QThread.

In your example, the “process()” method emits “finished()” signal to stop the thread. I ran into a situation where I have an infinite loop in the “process()” method. The loop updates my data, and uses the same to paint (update) a QWidget. Now, I want to break the loop (or stop the thread) on a button click. I am not sure when to emit “finished()” signal because the loop is infinite. Is there a way to send some signal (or put some condition) in the infinite loop to break it and emit “finished()”.

I guess there could be some tricky use of “connect” to make this happen. I am stuck and tried different ways. Now, Looking forward to your kind suggestions.

Thanks in advance.

Hi Maya,

I have a long running queue processor that I’m using a custom built thread pool for. I needed it to be custom so that I can do http callouts and get responses within each thread. When a process completes, I check to see if any of the threads in the pool are idle via the property (“hasWorker”) and if they don’t and theres another image fetch in the queue, than instead of killing the QThread, I re-assign it (“hasWorker”) move another worker object to it and then start the worker.

The problem is is that when there is nothing in the queue, as workers complete I’d like to shut down there threads. I am killing my threads via:

myThreadPool.removeOne(t);

t->quit();
t->wait(1000);
t->deleteLater();
pruneCount++;

However I’m getting system crashes every once and a while.

Could you help me understand the purpose of the wait(x) call — I saw that it was recommended on stack overflow.

Could the issue be that I’m not explicitly calling “start” and “finish” on these threads?

Any insights appreciated.

My workers are setup like:

connect(this, SIGNAL(work(int)), worker, SLOT(doWork(int)), Qt::QueuedConnection);
connect(this, &BaseManager::cancel, worker, &BaseWorker::onCancel, Qt::QueuedConnection);
connect(worker, &BaseWorker::finished, this, &BaseManager::finished, Qt::QueuedConnection);
connect(worker, &BaseWorker::finished, worker, &BaseWorker::deleteLater, Qt::QueuedConnection);

Thank you it really work for my multithread program to release the memory.
Avoid the program overflow crash.

Do you have another cpu post to study 🙂
I have another problem for 100% CPU using with Quad core.

Hi Maya,

Thanks for the wonderful explanations and example. Still found it after more than 6 years!
I don’t know if you’ve seen it but Qt docs now integrate this method!

Good job!

This framework works equally well for instances where you need a “catcher” thread that lives for the lifetime of the overall program.

Example: I use this framework surrounding a QSerialPort. The worker object owns and opens the serial port and receives work based on the QSerialPort::readyRead(); signal.

Additionally, I send work from the main object which spawned this thread, to which this worker replies with signals of it’s own, returning simple byte arrays of results or booleans.

So contrary to the militant view that threads should “do one thing and die”, this is a very simple and logical way to manage a DEVICE that is inherently slow even at it’s fastest speeds, is asynchronous in nature and thus is “in the way” in a GUI or in a controller object elsewhere. Using queued signals makes things orderly.

Many thanks Maya.

Hi Mitch,

Would you mind posting some samples of this method, as it is quite relevant to what I am about to implement with QSerialBus.

Thanks!

This is a great explanation on how to use Qthreads, I have been struggling with how to properly use them for years, using the inheritance and run() method. Because this was the only official documentation that I could find. This new method is really straight forward and makes more sense to me. But I am curious why the inheritance method is wrong? You did not really get into the pros and cons of the two methods. Also you did not mention on how to communicate with the thread, I have threads that operating on data continually and then need to wait for more data to process. I accomplish this with a while loop in the run() and a bool flag that data is ready, if no data is ready the while loop just executes sleep. Using a slot to signal the thread with a payload of data. I haven’t been able to find any definitive answer on how to do this effectively. Do you have a take on this?

Thank you for posting this, I have been looking along time on better ways to use QThreads.

The inheritance method isn’t necessarily wrong, just that it’s terrible overkill. As pointed out in the article, QThread is a wrapper around an OS-level thread. It’s easiest to just move one’s code onto an instance of this wrapper instead of having to deal with the details of how a QThread is implemented. Unless one’s need are very specific, naturally, but at that point one might wonder why one is using QThreads to begin with 🙂

Using signals and slots is the usual way to communicate between workers running in a QThread. Qt makes sure that this happens in thread-safe manner. If one needs to have one thread wait for another, one can also look at the use of condition variables and kin. I actually covered a lot of this (from a C++11 focus, though) in my latest book: Mastering C++ Multithreading.

Thanks. I was just about to implement my first Qt thread the “easy” way when I felt that something wasn’t quite right and discovered your blog.
FYI: There was some doubt expressed about why QThreads were originally subclassed, I found on blog.qt.io: “The original QThread class was abstract, so subclassing was necessary. It wasn’t until Qt 4.4 that QThread::run() gained a default implementation.”

What happens if worker::process is an infinite loop (using condition.wait for events)? Will this block the worker & thread from receiving any more signals?

Hi Maya, thanks for the wonderful explanation I have one doubt if we quite to a particular thread and calls its wait function to wait for some amount of time to quite and if that particular thread doesn’t quite or finished in the specified time than in this case can it cause the segmentation fault or can crash the main application?

I am wondering, is it valid to declare use a thread as a member of the worker, and start the thread in the worker’s constructor? For example:

class Worker : public QObject {
Q_OBJECT

public:
Worker();
~Worker();

private:
QThread thread;

Worker::Worker() {
thread = new QThread;
this->moveBranchToThread(thread);
thread ->start();

Worker::~Worker(){
thread->terminate();
thread->wait();

I have something like this that seems to be working but I’m not sure that I understand what is really happening behind the scenes. To me it makes sense to have the worker be responsible for its own thread, but I haven’t seen any examples like this so I might be misunderstanding something.

This is very good snippet describing how to use the threaded worker in the most simple case. More problems arise when we want to add more functionality to the worker, e.g. being able to abort its execution or run multiple times with or without recycling the thread. Then we need to hold the pointer/reference to the worker somewhere. We need to check its existence, whether the thread exists and is running etc. I am still trying hard to figure it out how to wrap this into a self-sustaining class which would not impose a burden of correct connecting the signals and doing complicated cleanup by the caller/owner, working well when the worker resides both on the stack or on the heap… Not so easy to figure it out… 😦

sorry to drag you back so many years…
Thank you for your post. Your example clarified several things for me.
But, I have a question about extending your suggested implementation to a list of workers and list of threads. I have an application that tries to capture logs from a user-selected list of devices. I would like to put each of the worker objects in its own thread.

What would the (newer) connect statement syntax be if I were to try something like:

QList dbgLogWritersList; // list of worker objects
QList qthreadsList; // list of thread managers

numCurrent = selectedDeviceList.count();

// instantiate a debug log writer object for each of the selected devices…
for (int i = 0 ; i moveToThread(qthreadsList.at(i));
connect(dbgLogWritersList.at(i), &DbgLogWriter::error(QString),
this, &DbgCaptureWindow::displayErrorFromCapture(QString) );
connect(dbgLogCapturesList->at(i), &DbgLogCapture::progress(QString),
this, &DbgCaptureWindow::updateProgress(int) );
connect(dbgLogCapturesList->at(i), &DbgLogCapture::finished(),
qthreads.at(i), &QThread::quit() );
connect(dbgLogCapturesList->at(i), &DbgLogCapture::finished(),
dbgLogCapturesList->at(i), &DbgLogCapture::deleteLater() );
// the key function run by the worker object, captureDbgLog
connect(qthreads.at(i), &QThread::started(),
dbgLogCapturesList->at(i), &DbgLogCapture::captureDbgLog() );
connect(qthreads.at(i), &QThread::finished(),
qthreads.at(i), &QThread::deleteLater() );
qthreadsList.at(i)->start();

The connect statements above do not compile. If you can provide a quick update on how your example gets extended to lists, that would be great!

I don’t know why QT company didn’t hire you quickly !
Thanks a lot sweety,
It will be great if you issued such article every week 😉
Appreciate your great efforts,
my regards

I know this is an old post, but I think this is the most helpful post I’ve seen when it comes using QThread. I implemented it just as you posted and it is so much easier than the other options out there.
My only issue is that I would like to pass a pointer to the process() program but get a runtime error stating that Qt can’t find my process() slot. I looked at using invokeMethod but that gave me an error as well.

Hello,
all this discussion is very interesting and is supposed to give opportunity to use (q)threads correctly in one of our favorite development platform.
Despite of this, I’m still confused with what to do exactly at the right place between the “main” UI thread and (other) threads/workers.
I’m currently trying to learn by myself to create my first example/test application with the “right method” you exposed long time ago !
My goal is to separate a particular set of procedures in a dedicated thread separated from the main UI (a simple QDialog), but making the separated thread/worker code to interact with the UI :
– send data or events to UI (by example : append text to a QTextBrowser widget, set progress percentage value to a QProgressBar, set text to a simple text/label widget, …)
– get data or events from UI (start / stop, yes / no simple button clicks, etc…)
I understand I have to worry about being sure of thread/worker code to execute in different context from the UI thread which is the true goal to reach…
But where exactly to make all the connect() init/steps and what side to declare and implement signals and slots?
If all my usefull code is in the (separate) thread/worker, I still don’t understand where “communication” things shall be done :
shall it be implemented in the run() method of the thread body or shall it be somewhere in the Worker::process() method ?
Where shall the slots be declared/coded ?
Where shall the signals be declared/coded ?
I would say a simple example of a simple QDialog main UI example, with a Start and Stop buttons and a simple progressBar updated relative to a simple number being incremented in the separate thread/worker would be very much “pedagogic” and appreciated.
Unless Start button clicked, the thread/worker would be “waiting” (sleeping ?) and once Start button clicked, the UI would send signal to the separate thread/worker to make it (them ?) start a loop incrementing a simple local number (local thread/worker integer variable), with small delay (if needed) after each increment to “save” cpu, each increment being followed by updating the progressBar widget belonging to the QDialog UI…
Am I “only a stupid dreamer” (thinking about Supertramp “Dreamer” song) to dream about such a not so easy example for beginner in Qt programming world and maze ?
Still trying to make things work, but still in the maze…
Kind regards to everybody and anybody that could help me to success in building my first “simple but right” Qt thread/worker example interacting with simple QDialog “main” UI thread…
Being breaking my teeth on the subject at current time…
Alain-Pierre ([email protected])

Yes, 17 days later (after jvz’s comment) I can still confirm what he says.
Do you have any interest in Python and PyQt5? I’ve translated your formula into it, but when it comes to testing I have encountered a slight problem actually cementing your code in place using TDD: specifically I can’t get unittest/pytest tests to make the signals you use trigger the slots you use. Check this out if interested: https://stackoverflow.com/questions/70135324/why-are-these-signal-related-tests-failing

One more comment… I’m sure you’re aware of many possible refinements to this basic recipe. But one that I have found is pretty necessary is to add a tiny delay to QThread.quit() and MyTask.deleteLater(). I’m working in PyQt5, so this is what it looks like:

# old_quit = self.thread.quit
# def _quit():
# def call_quit_delayed():
# old_quit()
# QtCore.QTimer.singleShot(1, call_quit_delayed)
# self.thread.quit = _quit

and in the MyTask class:

# def deleteLater(self):
# super_task = super()
# def call_deleteLater_delayed():
# super_task.deleteLater()
# QtCore.QTimer.singleShot(1, call_deleteLater_delayed)

… so that in each case a 1 ms delay is set up before the respective methods (true QThread.quit() and true MyTask.deleteLater()) fire.

The reason for this is that if you don’t do this, and any other functions/methods are connected to the finished signal of the, respectively, QThread or MyTask object, it is possible that that function/method will never fire, because the QThread will have “quit” or the MyTask will have “deleteLatered”.

Not surprisingly, perhaps, this is (in my experience, using PyQt5) an intermittent/inconsistent phenomenon: as, when several slots are connected to a given signal, you can’t know in which order they are going to be fired.

I’m not entirely sure my method works 100% of the time, but it *seems* to have solved the problem. NB typically you might want to use the finished signal of the QThread or MyTask to update the UI, or any number of other things.

Author

Maya Posch is a professional software developer. She has experience with various programming languages and platforms, including Android, Windows and Linux/BSDs.

Donate

Send me a few bucks if you like the articles on this site :)
Privacy & Cookies: This site uses cookies. By continuing to use this website, you agree to their use.
To find out more, including how to control cookies, see here: Cookie Policy