Qt Thread Concepts
Thread Support in Qt
Threading Basics
What Are Threads?
Threads are about doing things in parallel, just like processes. So how do threads differ from processes? While you are making calculations on a spreadsheet, there may also be a media player running on the same desktop playing your favorite song. Here is an example of two processes working in parallel: one running the spreadsheet program; one running a media player. Multitasking is a well known term for this. A closer look at the media player reveals that there are again things going on in parallel within one single process. While the media player is sending music to the audio driver, the user interface with all its bells and whistles is being constantly updated. This is what threads are for — concurrency within one single process.
So how is concurrency implemented? Parallel work on single core CPUs is an illusion which is somewhat similar to the illusion of moving images in cinema. For processes, the illusion is produced by interrupting the processor's work on one process after a very short time. Then the processor moves on to the next process. In order to switch between processes, the current program counter is saved and the next processor's program counter is loaded. This is not sufficient because the same needs to be done with registers and certain architecture and OS specific data.
Just as one CPU can power two or more processes, it is also possible to let the CPU run on two different code segments of one single process. When a process starts, it always executes one code segment and therefore the process is said to have one thread. However, the program may decide to start a second thread. Then, two different code sequences are processed simultaneously inside one process. Concurrency is achieved on single core CPUs by repeatedly saving program counters and registers then loading the next thread's program counters and registers. No cooperation from the program is required to cycle between the active threads. A thread may be in any state when the switch to the next thread occurs.
The current trend in CPU design is to have several cores. A typical single-threaded application can make use of only one core. However, a program with multiple threads can be assigned to multiple cores, making things happen in a truly concurrent way. As a result, distributing work to more than one thread can make a program run much faster on multicore CPUs because additional cores can be used.
Threads are about doing things in parallel, just like processes. So how do threads differ from processes? While you are making calculations on a spreadsheet, there may also be a media player running on the same desktop playing your favorite song. Here is an example of two processes working in parallel: one running the spreadsheet program; one running a media player. Multitasking is a well known term for this. A closer look at the media player reveals that there are again things going on in parallel within one single process. While the media player is sending music to the audio driver, the user interface with all its bells and whistles is being constantly updated. This is what threads are for — concurrency within one single process.
So how is concurrency implemented? Parallel work on single core CPUs is an illusion which is somewhat similar to the illusion of moving images in cinema. For processes, the illusion is produced by interrupting the processor's work on one process after a very short time. Then the processor moves on to the next process. In order to switch between processes, the current program counter is saved and the next processor's program counter is loaded. This is not sufficient because the same needs to be done with registers and certain architecture and OS specific data.
Just as one CPU can power two or more processes, it is also possible to let the CPU run on two different code segments of one single process. When a process starts, it always executes one code segment and therefore the process is said to have one thread. However, the program may decide to start a second thread. Then, two different code sequences are processed simultaneously inside one process. Concurrency is achieved on single core CPUs by repeatedly saving program counters and registers then loading the next thread's program counters and registers. No cooperation from the program is required to cycle between the active threads. A thread may be in any state when the switch to the next thread occurs.
The current trend in CPU design is to have several cores. A typical single-threaded application can make use of only one core. However, a program with multiple threads can be assigned to multiple cores, making things happen in a truly concurrent way. As a result, distributing work to more than one thread can make a program run much faster on multicore CPUs because additional cores can be used.
GUI Thread and Worker Thread
As mentioned, each program has one thread when it is started. This thread is called the "main thread" (also known as the "GUI thread" in Qt applications). The Qt GUI must run in this thread. All widgets and several related classes, for example QPixmap, don't work in secondary threads. A secondary thread is commonly referred to as a "worker thread" because it is used to offload processing work from the main thread.
As mentioned, each program has one thread when it is started. This thread is called the "main thread" (also known as the "GUI thread" in Qt applications). The Qt GUI must run in this thread. All widgets and several related classes, for example QPixmap, don't work in secondary threads. A secondary thread is commonly referred to as a "worker thread" because it is used to offload processing work from the main thread.
Simultaneous Access to Data
Each thread has its own stack, which means each thread has its own call history and local variables. Unlike processes, threads share the same address space. The following diagram shows how the building blocks of threads are located in memory. Program counter and registers of inactive threads are typically kept in kernel space. There is a shared copy of the code and a separate stack for each thread.

If two threads have a pointer to the same object, it is possible that both threads will access that object at the same time and this can potentially destroy the object's integrity. It's easy to imagine the many things that can go wrong when two methods of the same object are executed simultaneously.
Sometimes it is necessary to access one object from different threads; for example, when objects living in different threads need to communicate. Since threads use the same address space, it is easier and faster for threads to exchange data than it is for processes. Data does not have to be serialized and copied. Passing pointers is possible, but there must be a strict coordination of what thread touches which object. Simultaneous execution of operations on one object must be prevented. There are several ways of achieving this and some of them are described below.
So what can be done safely? All objects created in a thread can be used safely within that thread provided that other threads don't have references to them and objects don't have implicit coupling with other threads. Such implicit coupling may happen when data is shared between instances as with static members, singletons or global data. Familiarize yourself with the concept of thread safe and reentrant classes and functions.
Each thread has its own stack, which means each thread has its own call history and local variables. Unlike processes, threads share the same address space. The following diagram shows how the building blocks of threads are located in memory. Program counter and registers of inactive threads are typically kept in kernel space. There is a shared copy of the code and a separate stack for each thread.

If two threads have a pointer to the same object, it is possible that both threads will access that object at the same time and this can potentially destroy the object's integrity. It's easy to imagine the many things that can go wrong when two methods of the same object are executed simultaneously.
Sometimes it is necessary to access one object from different threads; for example, when objects living in different threads need to communicate. Since threads use the same address space, it is easier and faster for threads to exchange data than it is for processes. Data does not have to be serialized and copied. Passing pointers is possible, but there must be a strict coordination of what thread touches which object. Simultaneous execution of operations on one object must be prevented. There are several ways of achieving this and some of them are described below.
So what can be done safely? All objects created in a thread can be used safely within that thread provided that other threads don't have references to them and objects don't have implicit coupling with other threads. Such implicit coupling may happen when data is shared between instances as with static members, singletons or global data. Familiarize yourself with the concept of thread safe and reentrant classes and functions.
Using Threads
When to Use Alternatives to Threads
Developers need to be very careful with threads. It is easy to start other threads, but very hard to ensure that all shared data remains consistent. Problems are often hard to find because they may only show up once in a while or only on specific hardware configurations. Before creating threads to solve certain problems, possible alternatives should be considered.
Alternative Comment QEventLoop::processEvents() Calling QEventLoop::processEvents() repeatedly during a time-consuming calculation prevents GUI blocking. However, this solution doesn't scale well because the call to processEvents() may occur too often, or not often enough, depending on hardware. QTimer Background processing can sometimes be done conveniently using a timer to schedule execution of a slot at some point in the future. A timer with an interval of 0 will time out as soon as there are no more events to process. QSocketNotifier QNetworkAccessManager QIODevice::readyRead() This is an alternative to having one or multiple threads, each with a blocking read on a slow network connection. As long as the calculation in response to a chunk of network data can be executed quickly, this reactive design is better than synchronous waiting in threads. Reactive design is less error prone and energy efficient than threading. In many cases there are also performance benefits.
In general, it is recommended to only use safe and tested paths and to avoid introducing ad-hoc threading concepts. QtConcurrent provides an easy interface for distributing work to all of the processor's cores. The threading code is completely hidden in the QtConcurrent framework, so you don't have to take care of the details. However, QtConcurrent can't be used when communication with the running thread is needed, and it shouldn't be used to handle blocking operations.
Developers need to be very careful with threads. It is easy to start other threads, but very hard to ensure that all shared data remains consistent. Problems are often hard to find because they may only show up once in a while or only on specific hardware configurations. Before creating threads to solve certain problems, possible alternatives should be considered.
| Alternative | Comment |
|---|---|
| QEventLoop::processEvents() | Calling QEventLoop::processEvents() repeatedly during a time-consuming calculation prevents GUI blocking. However, this solution doesn't scale well because the call to processEvents() may occur too often, or not often enough, depending on hardware. |
| QTimer | Background processing can sometimes be done conveniently using a timer to schedule execution of a slot at some point in the future. A timer with an interval of 0 will time out as soon as there are no more events to process. |
| QSocketNotifier QNetworkAccessManager QIODevice::readyRead() | This is an alternative to having one or multiple threads, each with a blocking read on a slow network connection. As long as the calculation in response to a chunk of network data can be executed quickly, this reactive design is better than synchronous waiting in threads. Reactive design is less error prone and energy efficient than threading. In many cases there are also performance benefits. |
In general, it is recommended to only use safe and tested paths and to avoid introducing ad-hoc threading concepts. QtConcurrent provides an easy interface for distributing work to all of the processor's cores. The threading code is completely hidden in the QtConcurrent framework, so you don't have to take care of the details. However, QtConcurrent can't be used when communication with the running thread is needed, and it shouldn't be used to handle blocking operations.
Which Qt Thread Technology Should You Use?
Sometimes you want to do more than just running a method in the context of another thread. You may want to have an object which lives in another thread that provides a service to the GUI thread. Maybe you want another thread to stay alive forever to poll hardware ports and send a signal to the GUI thread when something noteworthy has happened. Qt provides different solutions for developing threaded applications. The right solution depends on the purpose of the new thread as well as on the thread's lifetime.
Lifetime of thread Development task Solution One call Run one method within another thread and quit the thread when the method is finished. Qt provides different solutions:- Write a function and run it with QtConcurrent::run()
- Derive a class from QRunnable and run it in the global thread pool with QThreadPool::globalInstance()->start()
- Derive a class from QThread, reimplement the QThread::run() method and use QThread::start() to run it.
One call Operations are to be performed on all items of a container. Processing should be performed using all available cores. A common example is to produce thumbnails from a list of images. QtConcurrent provides the map() function for applying operations on every container element, filter() for selecting container elements, and the option of specifying a reduce function for combining the remaining elements. One call A long running operation has to be put in another thread. During the course of processing, status information should be sent to the GUI thread. Use QThread, reimplement run and emit signals as needed. Connect the signals to the GUI thread's slots using queued signal/slot connections. Permanent Have an object living in another thread and let it perform different tasks upon request. This means communication to and from the worker thread is required. Derive a class from QObject and implement the necessary slots and signals, move the object to a thread with a running event loop and communicate with the object over queued signal/slot connections. Permanent Have an object living in another thread, let the object perform repeated tasks such as polling a port and enable communication with the GUI thread. Same as above but also use a timer in the worker thread to implement polling. However, the best solution for polling is to avoid it completely. Sometimes using QSocketNotifier is an alternative.
Sometimes you want to do more than just running a method in the context of another thread. You may want to have an object which lives in another thread that provides a service to the GUI thread. Maybe you want another thread to stay alive forever to poll hardware ports and send a signal to the GUI thread when something noteworthy has happened. Qt provides different solutions for developing threaded applications. The right solution depends on the purpose of the new thread as well as on the thread's lifetime.
| Lifetime of thread | Development task | Solution |
|---|---|---|
| One call | Run one method within another thread and quit the thread when the method is finished. | Qt provides different solutions:
|
| One call | Operations are to be performed on all items of a container. Processing should be performed using all available cores. A common example is to produce thumbnails from a list of images. | QtConcurrent provides the map() function for applying operations on every container element, filter() for selecting container elements, and the option of specifying a reduce function for combining the remaining elements. |
| One call | A long running operation has to be put in another thread. During the course of processing, status information should be sent to the GUI thread. | Use QThread, reimplement run and emit signals as needed. Connect the signals to the GUI thread's slots using queued signal/slot connections. |
| Permanent | Have an object living in another thread and let it perform different tasks upon request. This means communication to and from the worker thread is required. | Derive a class from QObject and implement the necessary slots and signals, move the object to a thread with a running event loop and communicate with the object over queued signal/slot connections. |
| Permanent | Have an object living in another thread, let the object perform repeated tasks such as polling a port and enable communication with the GUI thread. | Same as above but also use a timer in the worker thread to implement polling. However, the best solution for polling is to avoid it completely. Sometimes using QSocketNotifier is an alternative. |
Qt Thread Basics
QThread is a very convenient cross platform abstraction of native platform threads. Starting a thread is very simple. Let us look at a short piece of code that generates another thread which says hello in that thread and then exits.
// hellothread/hellothread.h
class HelloThread : public QThread
{
Q_OBJECT
private:
void run();
};
We derive a class from QThread and reimplement the run() method.
// hellothread/hellothread.cpp
void HelloThread::run()
{
qDebug() << "hello from worker thread " << thread()->currentThreadId();
}
The run method contains the code that will be run in a separate thread. In this example, a message containing the thread ID will be printed. QThread::start() will call the method in another thread.
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
HelloThread thread;
thread.start();
qDebug() << "hello from GUI thread " << app.thread()->currentThreadId();
thread.wait(); // do not exit before the thread is completed!
return 0;
}
To start the thread, our thread object needs to be instantiated. The start() method creates a new thread and calls the reimplemented run() method in this new thread. Right after start() is called, two program counters walk through the program code. The main function starts with only the GUI thread running and it should terminate with only the GUI thread running. Exiting the program when another thread is still busy is a programming error, and therefore, wait is called which blocks the calling thread until the run() method has completed.
This is the result of running the code:
hello from GUI thread 3079423696
hello from worker thread 3076111216
QThread is a very convenient cross platform abstraction of native platform threads. Starting a thread is very simple. Let us look at a short piece of code that generates another thread which says hello in that thread and then exits.
// hellothread/hellothread.h class HelloThread : public QThread { Q_OBJECT private: void run(); };
We derive a class from QThread and reimplement the run() method.
// hellothread/hellothread.cpp void HelloThread::run() { qDebug() << "hello from worker thread " << thread()->currentThreadId(); }
The run method contains the code that will be run in a separate thread. In this example, a message containing the thread ID will be printed. QThread::start() will call the method in another thread.
int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); HelloThread thread; thread.start(); qDebug() << "hello from GUI thread " << app.thread()->currentThreadId(); thread.wait(); // do not exit before the thread is completed! return 0; }
To start the thread, our thread object needs to be instantiated. The start() method creates a new thread and calls the reimplemented run() method in this new thread. Right after start() is called, two program counters walk through the program code. The main function starts with only the GUI thread running and it should terminate with only the GUI thread running. Exiting the program when another thread is still busy is a programming error, and therefore, wait is called which blocks the calling thread until the run() method has completed.
This is the result of running the code:
hello from GUI thread 3079423696 hello from worker thread 3076111216
QObject and Threads
As mentioned above, developers must always be careful when calling objects' methods from other threads. Thread affinity does not change this situation. Qt documentation marks several methods as thread-safe. postEvent() is a noteworthy example. A thread-safe method may be called from different threads simultaneously.
In cases where there is usually no concurrent access to methods, calling non-thread-safe methods of objects in other threads may work thousands of times before a concurrent access occurs, causing unexpected behavior. Writing test code does not entirely ensure thread correctness, but it is still important. On Linux, Valgrind and Helgrind can help detect threading errors.
As mentioned above, developers must always be careful when calling objects' methods from other threads. Thread affinity does not change this situation. Qt documentation marks several methods as thread-safe. postEvent() is a noteworthy example. A thread-safe method may be called from different threads simultaneously.
In cases where there is usually no concurrent access to methods, calling non-thread-safe methods of objects in other threads may work thousands of times before a concurrent access occurs, causing unexpected behavior. Writing test code does not entirely ensure thread correctness, but it is still important. On Linux, Valgrind and Helgrind can help detect threading errors.
Using a Mutex to Protect the Integrity of Data
A mutex is an object that has lock() and unlock() methods and remembers if it is already locked. A mutex is designed to be called from multiple threads. lock() returns immediately if the mutex is not locked. The next call from another thread will find the mutex in a locked state and then lock() will block the thread until the other thread calls unlock(). This functionality can make sure that a code section will be executed by only one thread at a time.
The following line sketches how a mutex can be used to make a method thread-safe:
void Worker::work()
{
this->mutex.lock(); // first thread can pass, other threads will be blocked here
doWork();
this->mutex.unlock();
}
What happens if one thread does not unlock a mutex? The result can be a frozen application. In the example above, an exception might be thrown and mutex.unlock() will never be reached. To prevent problems like this, QMutexLocker should be used.
void Worker::work()
{
QMutexLocker locker(&mutex); // Locks the mutex and unlocks when locker exits the scope
doWork();
}
This looks easy, but mutexes introduce a new class of problems: deadlocks. A deadlock happens when a thread waits for a mutex to become unlocked, but the mutex remains locked because the owning thread is waiting for the first thread to unlock it. The result is a frozen application. Mutexes can be used to make a method thread safe. Most Qt methods aren't thread safe because there is always a performance penalty when using mutexes.
It isn't always possible to lock and unlock a mutex in a method. Sometimes the need to lock spans several calls. For example, modifying a container with an iterator requires a sequence of several calls which should not be interrupted by other threads. In such a scenario, locking can be achieved with a mutex that is kept outside of the object to be manipulated. With an external mutex, the duration of locking can be adjusted to the needs of the operation. One disadvantage is that external mutexes aid locking, but do not enforce it because users of the object may forget to use it.
A mutex is an object that has lock() and unlock() methods and remembers if it is already locked. A mutex is designed to be called from multiple threads. lock() returns immediately if the mutex is not locked. The next call from another thread will find the mutex in a locked state and then lock() will block the thread until the other thread calls unlock(). This functionality can make sure that a code section will be executed by only one thread at a time.
The following line sketches how a mutex can be used to make a method thread-safe:
void Worker::work() { this->mutex.lock(); // first thread can pass, other threads will be blocked here doWork(); this->mutex.unlock(); }
What happens if one thread does not unlock a mutex? The result can be a frozen application. In the example above, an exception might be thrown and mutex.unlock() will never be reached. To prevent problems like this, QMutexLocker should be used.
void Worker::work() { QMutexLocker locker(&mutex); // Locks the mutex and unlocks when locker exits the scope doWork(); }
This looks easy, but mutexes introduce a new class of problems: deadlocks. A deadlock happens when a thread waits for a mutex to become unlocked, but the mutex remains locked because the owning thread is waiting for the first thread to unlock it. The result is a frozen application. Mutexes can be used to make a method thread safe. Most Qt methods aren't thread safe because there is always a performance penalty when using mutexes.
It isn't always possible to lock and unlock a mutex in a method. Sometimes the need to lock spans several calls. For example, modifying a container with an iterator requires a sequence of several calls which should not be interrupted by other threads. In such a scenario, locking can be achieved with a mutex that is kept outside of the object to be manipulated. With an external mutex, the duration of locking can be adjusted to the needs of the operation. One disadvantage is that external mutexes aid locking, but do not enforce it because users of the object may forget to use it.
Using the Event Loop to Prevent Data Corruption
The event loops of Qt are a very valuable tool for inter-thread communication. Every thread may have its own event loop. A safe way of calling a slot in another thread is by placing that call in another thread's event loop. This ensures that the target object finishes the method that is currently running before another method is started.
So how is it possible to put a method invocation in an event loop? Qt has two ways of doing this. One way is via queued signal-slot connections; the other way is to post an event with QCoreApplication::postEvent(). A queued signal-slot connection is a signal slot connection that is executed asynchronously. The internal implementation is based on posted events. The arguments of the signal are put into the event loop and the signal method returns immediately.
The connected slot will be executed at a time which depends on what else is in the event loop.
Communication via the event loop eliminates the deadlock problem we face when using mutexes. This is why we recommend using the event loop rather than locking an object using a mutex.
The event loops of Qt are a very valuable tool for inter-thread communication. Every thread may have its own event loop. A safe way of calling a slot in another thread is by placing that call in another thread's event loop. This ensures that the target object finishes the method that is currently running before another method is started.
So how is it possible to put a method invocation in an event loop? Qt has two ways of doing this. One way is via queued signal-slot connections; the other way is to post an event with QCoreApplication::postEvent(). A queued signal-slot connection is a signal slot connection that is executed asynchronously. The internal implementation is based on posted events. The arguments of the signal are put into the event loop and the signal method returns immediately.
The connected slot will be executed at a time which depends on what else is in the event loop.
Communication via the event loop eliminates the deadlock problem we face when using mutexes. This is why we recommend using the event loop rather than locking an object using a mutex.
Dealing with Asynchronous Execution
One way to obtain a worker thread's result is by waiting for the thread to terminate. In many cases, however, a blocking wait isn't acceptable. The alternative to a blocking wait are asynchronous result deliveries with either posted events or queued signals and slots. This generates a certain overhead because an operation's result does not appear on the next source line, but in a slot located somewhere else in the source file. Qt developers are used to working with this kind of asynchronous behavior because it is much similar to the kind of event-driven programming used in GUI applications.
One way to obtain a worker thread's result is by waiting for the thread to terminate. In many cases, however, a blocking wait isn't acceptable. The alternative to a blocking wait are asynchronous result deliveries with either posted events or queued signals and slots. This generates a certain overhead because an operation's result does not appear on the next source line, but in a slot located somewhere else in the source file. Qt developers are used to working with this kind of asynchronous behavior because it is much similar to the kind of event-driven programming used in GUI applications.
Examples
This tutorial comes with examples for Qt's three basic ways of working with threads. Two more examples show how to communicate with a running thread and how a QObject can be placed in another thread, providing service to the main thread.
- Using QThread as shown above
- Using the global QThreadPool
- Using QtConcurrent
- Communication with the GUI thread
- A permanent QObject in another thread provides service to the main thread
The following examples can all be compiled and run independently. The source can be found in the examples directory: examples/tutorials/threads/
This tutorial comes with examples for Qt's three basic ways of working with threads. Two more examples show how to communicate with a running thread and how a QObject can be placed in another thread, providing service to the main thread.
- Using QThread as shown above
- Using the global QThreadPool
- Using QtConcurrent
- Communication with the GUI thread
- A permanent QObject in another thread provides service to the main thread
The following examples can all be compiled and run independently. The source can be found in the examples directory: examples/tutorials/threads/
Example 1: Using the Thread Pool
Creating and destroying threads frequently can be expensive. To avoid the cost of thread creation, a thread pool can be used. A thread pool is a place where threads can be parked and fetched. We can write the same "hello thread" program as above using the global thread pool. We derive a class from QRunnable. The code we want to run in another thread needs to be placed in the reimplemented QRunnable::run() method.
// hellothreadpool/main.cpp
class Work : public QRunnable
{
public:
void run()
{
qDebug() << "Hello from thread " << QThread::currentThread();
}
};
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Work work;
work.setAutoDelete(false);
QThreadPool *threadPool = QThreadPool::globalInstance();
threadPool->start(&work);
qDebug() << "hello from GUI thread " << QThread::currentThread();
threadPool->waitForDone();
return 0;
}
We instantiate Work in main(), locate the global thread pool and use the QThreadPool::start() method. Now the thread pool runs our worker in another thread. Using the thread pool has a performance advantage because threads are not destroyed after they have finished running. They are kept in a pool and wait to be used again later.
Creating and destroying threads frequently can be expensive. To avoid the cost of thread creation, a thread pool can be used. A thread pool is a place where threads can be parked and fetched. We can write the same "hello thread" program as above using the global thread pool. We derive a class from QRunnable. The code we want to run in another thread needs to be placed in the reimplemented QRunnable::run() method.
// hellothreadpool/main.cpp class Work : public QRunnable { public: void run() { qDebug() << "Hello from thread " << QThread::currentThread(); } }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); Work work; work.setAutoDelete(false); QThreadPool *threadPool = QThreadPool::globalInstance(); threadPool->start(&work); qDebug() << "hello from GUI thread " << QThread::currentThread(); threadPool->waitForDone(); return 0; }
We instantiate Work in main(), locate the global thread pool and use the QThreadPool::start() method. Now the thread pool runs our worker in another thread. Using the thread pool has a performance advantage because threads are not destroyed after they have finished running. They are kept in a pool and wait to be used again later.
Example 2: Using QtConcurrent
// helloconcurrent/main.cpp
void hello()
{
qDebug() << "Hello from thread " << QThread::currentThread();
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QFuture<void> future = QtConcurrent::run(hello);
qDebug() << "hello from GUI thread " << QThread::currentThread();
future.waitForFinished();
return 0;
}
We write a global function hello() to implement the work. QtConcurrent::run() is used to run the function in another thread. The result is a QFuture. QFuture provides a method called waitForFinished(), which blocks until the calculation is completed. The real power of QtConcurrent becomes visible when data can be made available in a container. QtConcurrent provides several functions that are able to process itemized data on all available cores simultaneously. The use of QtConcurrent is very similar to applying an STL algorithm to an STL container. QtConcurrent Map is a very short and clear example about how a container of images can be scaled on all available cores. The image scaling example uses the blocking variants of the functions used. For every blocking function there is also a non-blocking, asynchronous counterpart. Getting results asynchronously is implemented with QFuture and QFutureWatcher.
// helloconcurrent/main.cpp void hello() { qDebug() << "Hello from thread " << QThread::currentThread(); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QFuture<void> future = QtConcurrent::run(hello); qDebug() << "hello from GUI thread " << QThread::currentThread(); future.waitForFinished(); return 0; }
We write a global function hello() to implement the work. QtConcurrent::run() is used to run the function in another thread. The result is a QFuture. QFuture provides a method called waitForFinished(), which blocks until the calculation is completed. The real power of QtConcurrent becomes visible when data can be made available in a container. QtConcurrent provides several functions that are able to process itemized data on all available cores simultaneously. The use of QtConcurrent is very similar to applying an STL algorithm to an STL container. QtConcurrent Map is a very short and clear example about how a container of images can be scaled on all available cores. The image scaling example uses the blocking variants of the functions used. For every blocking function there is also a non-blocking, asynchronous counterpart. Getting results asynchronously is implemented with QFuture and QFutureWatcher.
Example 3: Clock

We want to produce a clock application. The application has a GUI and a worker thread. The worker thread checks every 10 milliseconds what time it is. If the formatted time has changed, the result will be sent to the GUI thread where it is displayed.
Of course, this is an overly complicated way of designing a clock and, actually, a separate thread is unnecessary. We would be better off placing the timer in the main thread because the calculation made in the timer slot is very short-lived. This example is purely for instructional use and shows how to communicate from a worker thread to a GUI thread. Note that communication in this direction is easy. We only need to add a signal to QThread and make a queued signal/slot connection to the main thread. Communication from the GUI to the worker thread is shown in the next example.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// build gui
QWidget widget;
QLabel *label = new QLabel;
QHBoxLayout *layout = new QHBoxLayout(&widget);
layout->addWidget(label);
widget.setWindowTitle("clock");
//instantiate thread object
ClockThread clockThread;
QObject::connect(&clockThread, SIGNAL(sendTime(QString)), label, SLOT(setText(QString)), Qt::QueuedConnection);
clockThread.start();
widget.show();
app.exec();
clockThread.quit();
clockThread.wait();
return 0;
}
We've connected the clockThread with the label. The connection must be a queued signal-slot connection because we want to put the call in the event loop.
// clock/clockthread.h
class ClockThread : public QThread
{
Q_OBJECT
signals:
void sendTime(QString time);
private:
void run();
QString m_lastTime;
private slots:
void timerHit();
};
We have derived a class from QThread and declared the sendTime() signal.
// clock/clockthread.cpp
void ClockThread::run()
{
QTimer timer;
connect(&timer, SIGNAL(timeout()), this, SLOT(timerHit()), Qt::DirectConnection);
timer.setInterval(10);
timer.start(); // puts one event in the threads event queue
exec();
timer.stop();
}
void ClockThread::timerHit()
{
QString newTime= QDateTime::currentDateTime().toString("ddd MMMM d yy, hh:mm:ss");
if(m_lastTime != newTime ){
m_lastTime = newTime;
emit sendTime(newTime) ;
}
}
The trickiest part of this example is that the timer is connected to its slot via a direct connection. A default connection would produce a queued signal-slot connection because the connected objects live in different threads; remember that QThread does not live in the thread it creates.
Still it is safe to access ClockThread::timerHit() from the worker thread because ClockThread::timerHit() is private and only touches local variables and a private member that isn't touched by public methods. QDateTime::currentDateTime() isn't marked as thread-safe in Qt documentation, however we can get away with using it in this small example because we know that the QDateTime::currentDateTime() static method isn't used in any other threads.

We want to produce a clock application. The application has a GUI and a worker thread. The worker thread checks every 10 milliseconds what time it is. If the formatted time has changed, the result will be sent to the GUI thread where it is displayed.
Of course, this is an overly complicated way of designing a clock and, actually, a separate thread is unnecessary. We would be better off placing the timer in the main thread because the calculation made in the timer slot is very short-lived. This example is purely for instructional use and shows how to communicate from a worker thread to a GUI thread. Note that communication in this direction is easy. We only need to add a signal to QThread and make a queued signal/slot connection to the main thread. Communication from the GUI to the worker thread is shown in the next example.
int main(int argc, char *argv[]) { QApplication app(argc, argv); // build gui QWidget widget; QLabel *label = new QLabel; QHBoxLayout *layout = new QHBoxLayout(&widget); layout->addWidget(label); widget.setWindowTitle("clock"); //instantiate thread object ClockThread clockThread; QObject::connect(&clockThread, SIGNAL(sendTime(QString)), label, SLOT(setText(QString)), Qt::QueuedConnection); clockThread.start(); widget.show(); app.exec(); clockThread.quit(); clockThread.wait(); return 0; }
We've connected the clockThread with the label. The connection must be a queued signal-slot connection because we want to put the call in the event loop.
// clock/clockthread.h class ClockThread : public QThread { Q_OBJECT signals: void sendTime(QString time); private: void run(); QString m_lastTime; private slots: void timerHit(); };
We have derived a class from QThread and declared the sendTime() signal.
// clock/clockthread.cpp void ClockThread::run() { QTimer timer; connect(&timer, SIGNAL(timeout()), this, SLOT(timerHit()), Qt::DirectConnection); timer.setInterval(10); timer.start(); // puts one event in the threads event queue exec(); timer.stop(); } void ClockThread::timerHit() { QString newTime= QDateTime::currentDateTime().toString("ddd MMMM d yy, hh:mm:ss"); if(m_lastTime != newTime ){ m_lastTime = newTime; emit sendTime(newTime) ; } }
The trickiest part of this example is that the timer is connected to its slot via a direct connection. A default connection would produce a queued signal-slot connection because the connected objects live in different threads; remember that QThread does not live in the thread it creates.
Still it is safe to access ClockThread::timerHit() from the worker thread because ClockThread::timerHit() is private and only touches local variables and a private member that isn't touched by public methods. QDateTime::currentDateTime() isn't marked as thread-safe in Qt documentation, however we can get away with using it in this small example because we know that the QDateTime::currentDateTime() static method isn't used in any other threads.
Example 4: A Permanent Thread
This example shows how it is possible to have a QObject in a worker thread that accepts requests from the GUI thread, does polling using a timer and continuously reports results back to the GUI thread. The actual work including the polling must be implemented in a class derived from QObject. We have called this class WorkerObject in the code shown below. The thread-specific code is hidden in a class called Thread, derived from QThread. Thread has two additional public members. The launchWorker() member takes the worker object and moves it to another thread with a started event loop. The call blocks for a very short moment until the thread creation operation is completed, allowing the worker object to be used again on the next line. The Thread class's code is short but somewhat involved, so we only show how to use the class.
// movedobject/main.cpp
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Thread thread;
qDebug() << "main thread ID: " << app.thread()->currentThreadId();
WorkerObject *worker = new WorkerObject;
thread.launchWorker(worker);
QMetaObject::invokeMethod(worker, "doWork", Qt::QueuedConnection);
QMetaObject::invokeMethod(worker, "startPolling", Qt::QueuedConnection, Q_ARG(int, 500));
//let application produce output for 3 seconds and quit
QTimer::singleShot(3000, &app, SLOT(quit()));
app.exec();
thread.stop();
thread.wait();
delete worker;
return 0;
}
QMetaObject::invokeMethod() calls a slot via the event loop. The worker object's methods should not be called directly after the object has been moved to another thread. We let the worker thread do some work and polling, and use a timer to shut the application down after 3 seconds. Shutting the worker down needs some care. We call Thread::stop() to exit the event loop. We wait for the thread to terminate and, after this has occurred, we delete the worker.
This example shows how it is possible to have a QObject in a worker thread that accepts requests from the GUI thread, does polling using a timer and continuously reports results back to the GUI thread. The actual work including the polling must be implemented in a class derived from QObject. We have called this class WorkerObject in the code shown below. The thread-specific code is hidden in a class called Thread, derived from QThread. Thread has two additional public members. The launchWorker() member takes the worker object and moves it to another thread with a started event loop. The call blocks for a very short moment until the thread creation operation is completed, allowing the worker object to be used again on the next line. The Thread class's code is short but somewhat involved, so we only show how to use the class.
// movedobject/main.cpp int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); Thread thread; qDebug() << "main thread ID: " << app.thread()->currentThreadId(); WorkerObject *worker = new WorkerObject; thread.launchWorker(worker); QMetaObject::invokeMethod(worker, "doWork", Qt::QueuedConnection); QMetaObject::invokeMethod(worker, "startPolling", Qt::QueuedConnection, Q_ARG(int, 500)); //let application produce output for 3 seconds and quit QTimer::singleShot(3000, &app, SLOT(quit())); app.exec(); thread.stop(); thread.wait(); delete worker; return 0; }
QMetaObject::invokeMethod() calls a slot via the event loop. The worker object's methods should not be called directly after the object has been moved to another thread. We let the worker thread do some work and polling, and use a timer to shut the application down after 3 seconds. Shutting the worker down needs some care. We call Thread::stop() to exit the event loop. We wait for the thread to terminate and, after this has occurred, we delete the worker.
Digging Deeper
Threading is a very complicated subject. Qt offers more classes for threading than we have presented in this tutorial. The following materials can help you go into the subject in more depth:
- Good video tutorials about threads with Qt can be found in the material from the Training Day at Qt Developer Days 2009.
- The Thread Support in Qt document is a good starting point into the reference documentation.
- Qt comes with several additional examples for QThread and QtConcurrent.
- Several good books describe how to work with Qt threads. The most extensive coverage can be found in Advanced Qt Programming by Mark Summerfield, Prentice Hall - roughly 70 of 500 pages cover QThread and QtConcurrent.
Threading is a very complicated subject. Qt offers more classes for threading than we have presented in this tutorial. The following materials can help you go into the subject in more depth:
- Good video tutorials about threads with Qt can be found in the material from the Training Day at Qt Developer Days 2009.
- The Thread Support in Qt document is a good starting point into the reference documentation.
- Qt comes with several additional examples for QThread and QtConcurrent.
- Several good books describe how to work with Qt threads. The most extensive coverage can be found in Advanced Qt Programming by Mark Summerfield, Prentice Hall - roughly 70 of 500 pages cover QThread and QtConcurrent.
Running a Function in a Separate Thread
To run a function in another thread, use QtConcurrent::run():
extern void aFunction(); QFuture<void> future = QtConcurrent::run(aFunction);
This will run aFunction in a separate thread obtained from the default QThreadPool. You can use the QFuture and QFutureWatcher classes to monitor the status of the function.
Passing Arguments to the Function
Passing arguments to the function is done by adding them to the QtConcurrent::run() call immediately after the function name. For example:
extern void aFunctionWithArguments(int arg1, double arg2, const QString &string); int integer = ...; double floatingPoint = ...; QString string = ...; QFuture<void> future = QtConcurrent::run(aFunctionWithArguments, integer, floatingPoint, string);
A copy of each argument is made at the point where QtConcurrent::run() is called, and these values are passed to the thread when it begins executing the function. Changes made to the arguments after calling QtConcurrent::run() are not visible to the thread.
Returning Values from the Function
Any return value from the function is available via QFuture:
extern QString functionReturningAString(); QFuture<QString> future = QtConcurrent::run(functionReturningAString); ... QString result = future.result();
As documented above, passing arguments is done like this:
extern QString someFunction(const QByteArray &input); QByteArray bytearray = ...; QFuture<QString> future = QtConcurrent::run(someFunction, bytearray); ... QString result = future.result();
Note that the QFuture::result() function blocks and waits for the result to become available. Use QFutureWatcher to get notification when the function has finished execution and the result is available.
Additional API Features
Using Member Functions
QtConcurrent::run() also accepts pointers to member functions. The first argument must be either a const reference or a pointer to an instance of the class. Passing by const reference is useful when calling const member functions; passing by pointer is useful for calling non-const member functions that modify the instance.
For example, calling QByteArray::split() (a const member function) in a separate thread is done like this:
// call 'QList<QByteArray> QByteArray::split(char sep) const' in a separate thread QByteArray bytearray = "hello world"; QFuture<QList<QByteArray> > future = QtConcurrent::run(bytearray, &QByteArray::split, ','); ... QList<QByteArray> result = future.result();
Calling a non-const member function is done like this:
// call 'void QImage::invertPixels(InvertMode mode)' in a separate thread QImage image = ...; QFuture<void> future = QtConcurrent::run(&image, &QImage::invertPixels, QImage::InvertRgba); ... future.waitForFinished(); // At this point, the pixels in 'image' have been inverted
Using Bound Function Arguments
Note that Qt does not provide support for bound functions. This is provided by 3rd party libraries like Boost or C++ TR1 Library Extensions.
You can use boost::bind() or std::tr1::bind() to bind a number of arguments to a function when called. There are number of reasons for doing this:
- To call a function that takes more than 5 arguments.
- To simplify calling a function with constant arguments.
- Changing the order of arguments.
See the documentation for the relevant functions for details on how to use the bind API.
Calling a bound function is done like this:
void someFunction(int arg1, double arg2); QFuture<void> future = QtConcurrent::run(boost::bind(someFunction, 1, 2.0)); ...
QThreadPool Class
The QThreadPool class manages a collection of QThreads. More...
| Header: | #include <QThreadPool> |
| Since: | Qt 4.4 |
| Inherits: | QObject |
Note: All functions in this class are thread-safe.
Properties
- activeThreadCount : const int
- expiryTimeout : int
- maxThreadCount : int
- 1 property inherited from QObject
Public Functions
| QThreadPool(QObject * parent = 0) | |
| ~QThreadPool() | |
| int | activeThreadCount() const |
| int | expiryTimeout() const |
| int | maxThreadCount() const |
| void | releaseThread() |
| void | reserveThread() |
| void | setExpiryTimeout(int expiryTimeout) |
| void | setMaxThreadCount(int maxThreadCount) |
| void | start(QRunnable * runnable, int priority = 0) |
| bool | tryStart(QRunnable * runnable) |
| void | waitForDone() |
| bool | waitForDone(int msecs) |
- 29 public functions inherited from QObject
Static Public Members
| QThreadPool * | globalInstance() |
- 7 static public members inherited from QObject
Additional Inherited Members
- 1 public slot inherited from QObject
- 1 signal inherited from QObject
- 8 protected functions inherited from QObject
Detailed Description
The QThreadPool class manages a collection of QThreads.
QThreadPool manages and recyles individual QThread objects to help reduce thread creation costs in programs that use threads. Each Qt application has one global QThreadPool object, which can be accessed by calling globalInstance().
To use one of the QThreadPool threads, subclass QRunnable and implement the run() virtual function. Then create an object of that class and pass it to QThreadPool::start().
class HelloWorldTask : public QRunnable { void run() { qDebug() << "Hello world from thread" << QThread::currentThread(); } } HelloWorldTask *hello = new HelloWorldTask(); // QThreadPool takes ownership and deletes 'hello' automatically QThreadPool::globalInstance()->start(hello);
QThreadPool deletes the QRunnable automatically by default. Use QRunnable::setAutoDelete() to change the auto-deletion flag.
QThreadPool supports executing the same QRunnable more than once by calling tryStart(this) from within QRunnable::run(). If autoDelete is enabled the QRunnable will be deleted when the last thread exits the run function. Calling start() multiple times with the same QRunnable when autoDelete is enabled creates a race condition and is not recommended.
Threads that are unused for a certain amount of time will expire. The default expiry timeout is 30000 milliseconds (30 seconds). This can be changed using setExpiryTimeout(). Setting a negative expiry timeout disables the expiry mechanism.
Call maxThreadCount() to query the maximum number of threads to be used. If needed, you can change the limit with setMaxThreadCount(). The default maxThreadCount() is QThread::idealThreadCount(). The activeThreadCount() function returns the number of threads currently doing work.
The reserveThread() function reserves a thread for external use. Use releaseThread() when your are done with the thread, so that it may be reused. Essentially, these functions temporarily increase or reduce the active thread count and are useful when implementing time-consuming operations that are not visible to the QThreadPool.
Note that QThreadPool is a low-level class for managing threads, see QtConcurrent::run() or the other Qt Concurrent APIs for higher level alternatives.
See also QRunnable.
Property Documentation
activeThreadCount : const int
This property represents the number of active threads in the thread pool.
Note: It is possible for this function to return a value that is greater than maxThreadCount(). See reserveThread() for more details.
Access functions:
| int | activeThreadCount() const |
See also reserveThread() and releaseThread().
expiryTimeout : int
Threads that are unused for expiryTimeout milliseconds are considered to have expired and will exit. Such threads will be restarted as needed. The default expiryTimeout is 30000 milliseconds (30 seconds). If expiryTimeout is negative, newly created threads will not expire, e.g., they will not exit until the thread pool is destroyed.
Note that setting expiryTimeout has no effect on already running threads. Only newly created threads will use the new expiryTimeout. We recommend setting the expiryTimeout immediately after creating the thread pool, but before calling start().
Access functions:
| int | expiryTimeout() const |
| void | setExpiryTimeout(int expiryTimeout) |
maxThreadCount : int
This property represents the maximum number of threads used by the thread pool.
Note: The thread pool will always use at least 1 thread, even if maxThreadCount limit is zero or negative.
The default maxThreadCount is QThread::idealThreadCount().
Access functions:
| int | maxThreadCount() const |
| void | setMaxThreadCount(int maxThreadCount) |
Member Function Documentation
QThreadPool::QThreadPool(QObject * parent = 0)
Constructs a thread pool with the given parent.
QThreadPool::~QThreadPool()
Destroys the QThreadPool. This function will block until all runnables have been completed.
[static]QThreadPool * QThreadPool::globalInstance()
Returns the global QThreadPool instance.
void QThreadPool::releaseThread()
Releases a thread previously reserved by a call to reserveThread().
Note: Calling this function without previously reserving a thread temporarily increases maxThreadCount(). This is useful when a thread goes to sleep waiting for more work, allowing other threads to continue. Be sure to call reserveThread() when done waiting, so that the thread pool can correctly maintain the activeThreadCount().
See also reserveThread().
void QThreadPool::reserveThread()
Reserves one thread, disregarding activeThreadCount() and maxThreadCount().
Once you are done with the thread, call releaseThread() to allow it to be reused.
Note: This function will always increase the number of active threads. This means that by using this function, it is possible for activeThreadCount() to return a value greater than maxThreadCount() .
See also releaseThread().
void QThreadPool::start(QRunnable * runnable, int priority = 0)
Reserves a thread and uses it to run runnable, unless this thread will make the current thread count exceed maxThreadCount(). In that case, runnable is added to a run queue instead. The priority argument can be used to control the run queue's order of execution.
Note that the thread pool takes ownership of the runnable if runnable->autoDelete() returns true, and the runnable will be deleted automatically by the thread pool after the runnable->run() returns. If runnable->autoDelete() returns false, ownership of runnable remains with the caller. Note that changing the auto-deletion on runnable after calling this functions results in undefined behavior.
bool QThreadPool::tryStart(QRunnable * runnable)
Attempts to reserve a thread to run runnable.
If no threads are available at the time of calling, then this function does nothing and returns false. Otherwise, runnable is run immediately using one available thread and this function returns true.
Note that the thread pool takes ownership of the runnable if runnable->autoDelete() returns true, and the runnable will be deleted automatically by the thread pool after the runnable->run() returns. If runnable->autoDelete() returns false, ownership of runnable remains with the caller. Note that changing the auto-deletion on runnable after calling this function results in undefined behavior.
void QThreadPool::waitForDone()
Waits for each thread to exit and removes all threads from the thread pool.
bool QThreadPool::waitForDone(int msecs)
This function overloads waitForDone().
Waits up to msecs milliseconds for all threads to exit and removes all threads from the thread pool. Returns true if all threads were removed; otherwise it returns false.
This function was introduced in Qt 4.8.
QThread FAQ in Interviews
The run() implementation is for a thread what the main() entry point is for the application.
Q) Different types of thread?
http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/
http://ynonperek.com/course/qt/threads.html
First:
QThread MyThread;
this->moveToThread(&MyThread);
//”this” makes object of current class to run in thread
MyThread.start();
Second:
Subclass Qthread and override run()
Third:
QtConcurrent::run(this, &Camera::firstStartThreadProc);
OR
QFuture<void> f1 = QtConcurrent::run(this, &CanDTC::readThreadProc);
USAGE-01
#include <QtCore>
class Thread : public QThread
{
private:
void run()
{
qDebug()<<"From worker thread: "<<currentThreadId();
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug()<<"From main thread: "<<QThread::currentThreadId();
Thread t;
QObject::connect(&t, SIGNAL(finished()), &a, SLOT(quit()));
t.start();
return a.exec();
}
Q) What happens if Qthread subclas declartion is in cpp and anot in header file?
You need to have a line at the bottom of your source file: #include "main.moc"
That's because the declaration of class Thread isn't in a header - it's in a .cpp file. So by default moc won't run on it. Adding the line does two things:
it signals to qmake and moc that moc has to process the .cpp file
it causes the stuff that moc generates to be pulled in by the compile step
So after adding that line you'll need to rerun qmake so it can update the makefiles to cause main.moc to be generated.
Q) What is the difference between QueuedConnection and normal connection in connect Qt?
// connect signal-slots for decoupling
QObject::connect (this, SIGNAL(setCurrentTaskSignal(int)), this,
SLOT(SetCurrentTaskSlot(int)), Qt::QueuedConnection);
Note that QueuedConnection doesn't mean that something is in different thread. QueuedConnection means only that when signal is emitted, corresponding slot won't be called directly. It will be queued on event loop, and will be processed when control will be given back to event loop
One uses a queued connection to ensure that the signal will be delivered from within the event loop, and not immediately from the emit site as happens with direct connection. Direct connection is conceptually a set of calls to function pointers on a list. Queued connection is conceptually an event sent to a clever receiver who can execute a function call based on the contents of the event.
Qt.QueuedConnection -> When emitted, the signal is queued until the event loop is able to deliver it to the slot.
Qt.BlockingQueuedConnection -> Same as QueuedConnection, except that the current thread blocks until the slot has been delivered. This connection type should only be used for receivers in a different thread. Note that misuse of this type can lead to dead locks in your application.
Direct signal-slot connection is nothing else but a chain of synchronous or direct C++ function calls.
A queued signal-slot connection is nothing else but an asynchronous function call
Q) When is Qthread begin executing?
QThreads begin executing in run().
By default, run() starts the event loop by calling exec()...".
Q) By whom and when is run() method called in Qthread?
The run() method is called automagically by Qt when the caller calls start() on your thread
Q) How qthread can be used?
To be able to use one of the QThreadPool threads, we have to subclass QRunnable and implement the run() method. After that, we have to create an instance of the QRunnable subclass and pass it to QThreadPool::start().
//start->run->qthread.
Q)Wtat is the main difference between a process and a thread?
The main difference between a process and a thread is that each process is executed in a separate address space, whereas each thread uses the same address space of a process.
A process can have multiple threads.
Threads share the heap, but each thread of execution has its own call stack.
Q) Difference between QThread runnable and QtConcurrent?
QThread provides a low-level class that can be used for explicit creation of long-running threads.
Using QtConcurrent's functional map/filter/reduce algorithms, which apply functions in parallel to each item in a container, you can write a program that automatically takes advantage of the system's multiple cores by distributing the processing across the threads managed by the thread pool. Alternatively, you can use QRunnable as a base class for the Command pattern and schedule work with QtConcurrent::run(). In these cases, you do not need to create threads explicitly or manage them directly – you can simply describe the pieces of work as objects with the right interface.
QtConcurrent runs a pool of threads and it is a higher level API not well-suited to run a large number of blocking operations:
If you have CPU-bound work to do and want to distribute it across multiple cores, you can break up your work into QRunnables and make those thread-safe by following these recomendations.
Distribute the CPU-heavy calculations across multiple threads using QtConcurrent algorithms whenever possible, instead of writing your own QThread code.
Do not access the GUI (this includes any QWidget-derived class, QPixmap, and other graphics-card specific classes) from any thread other than the main thread. This includes read access like querying the text entered into a QlineEdit.
Q) Suppose your application needs to run a function in multiple threads the number of which is more than the number of CPU cores/threads.
One way is to use QtConcurrent and setting the maximum thread count :
MyClass *obj = new MyClass;
QThreadPool::globalInstance()->setMaxThreadCount(30);
for(int i=0;i<30;i++)
QtConcurrent::run(obj, &MyClass::someFunction);
Another way is to have multiple objects and move them to different threads using moveToThread :
for(int i=0;i<30;i++)
{
MyClass *obj = new MyClass;
QThread *th = new QThread();
obj->moveToThread(th);
connect(th, SIGNAL(started()), obj, SLOT(someFunction()) );
connect(obj, SIGNAL(workFinished()), th, SLOT(quit()) );
connect(th, SIGNAL(finished()), obj, SLOT(deleteLater()) );
connect(th, SIGNAL(finished()), th, SLOT(deleteLater()) );
th->start();
}
Comments
Post a Comment