Qt Execute Slot In Another Thread

  
Qt Execute Slot In Another Thread 7,0/10 1941 votes

However, you are free to connect the Worker's slots to any signal, from any object, in any thread. It is safe to connect signals and slots across different threads, thanks to a mechanism called queued connections. Another way to make code run in a separate thread, is to subclass QThread and reimplement run. ‒ Slot is called immediately, by simple function call ‒ Synchronous, same thread. QueuedConnection: ‒ An event is posted so the slot is called later ‒ Asynchronous, potentially run in another thread. BlockingQueuedConnection: ‒ Same as QueuedConnection, but includes a semaphore to wait ‒ Synchronous, always run in another thread.

EnArBgDeElEsFaFiFrHiHuItJaKnKoMsNlPlPtRuSqThTrUkZh

  • The Thread::doWork function lives in another thread than Object::started, which has been created in run. If the Thread has been instantiated in the UI Thread, this is where doWork would have belonged. This system is powerful but complex. To make things more simple, Qt favors the worker model.
  • The QSlotObject is a wrapper around the slot that will help calling it. It also knows the type of the signal arguments so it can do the proper type conversion. We use ListLeft to only pass the same number as argument as the slot, which allows connecting a signal with many arguments to a slot with less arguments.

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.

Those who have discovered the joys of the Qt framework may assume that threads in Qt are just like this, and they would be right. However, there are several different ways to use threads in Qt, and it might not be obvious which approach to choose. The article, Multithreading Technologies in Qt, compares the different approaches.

The rest of this article demonstrates one of these methods: QThread + a worker QObject. This method is intended for use cases which involve event-driven programming and signals + slots across threads.

Usage with Worker class

The main thing in this example 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. To use it, prepare a QObject subclass 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.

Declare Worker class

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

class Worker : public QObject {

Thread

public:

public slots:

signals:

private:

};

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.

Worker::Worker() { // Constructor

}

Worker::~Worker() { // Destructor

}

void Worker::process() { // Process. Start processing data.

}

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.

Create a new Worker instance

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.


External Links

  1. Maya Posch's blog, http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
  2. Qt Blog on subclassing QThread is wrong, [1]
  3. Woboq Blog on subclassing QThread is not always wrong, [2]
Retrieved from 'https://wiki.qt.io/index.php?title=QThreads_general_usage&oldid=18828'
Home All Classes Main Classes Annotated Grouped Classes Functions

Qt provides thread support in the form of basic platform-independentthreading classes, a thread-safe way of posting events, and a globalQt library lock that allows you to call Qt methods from differentthreads.

This document is intended for an audience that has knowledge andexperience with multithreaded applications. Recommended reading:

Enabling Thread Support

Qt Execute Slot In Another Thread Size

When Qt is installed on Windows, thread support is an option on somecompilers.

On Mac OS X and Unix, thread support is enabled by adding the-thread option when running the configure script. On Unixplatforms where multithreaded programs must be linked in special ways,such as with a special libc, installation will create a separatelibrary, libqt-mt and hence threaded programs must be linkedagainst this library (with -lqt-mt) rather than the standard Qtlibrary.

On both platforms, you should compile with the macro QT_THREAD_SUPPORT defined (e.g. compile with-DQT_THREAD_SUPPORT). On Windows, this is usually done by anentry in qconfig.h.

The Thread Classes

These classes are built into the Qt library when thread support is enabled:

  • QThread - Provides the means to start a new thread, which beginsexecution in your reimplementation of QThread::run(). This is similarto the Java thread class.
  • QMutex - Provides a mutual exclusion lock (also know as a mutex).
  • QMutexLocker - A convenience class which automatically locks andunlocks a QMutex. QMutexLocker is useful in complicated code, or incode which uses exceptions. See the documentation for more details.
  • QWaitCondition - Provides a way for threads to go to sleep untilwoken up by another thread.
  • QSemaphore - Provides a simple integer semaphore.

Important Information

When using Qt in a multithreaded program, it is important tounderstand the definition of the terms reentrant and thread-safe:

  • reentrant - Describes a function which can be calledsimultaneously by multiple threads when each invocation of thefunction references unique data. Calling a reentrant functionsimultaneously with the same data is not safe, and such invocationsshould be serialized.
  • thread-safe - Describes a function which can be calledsimultaneously by multiple threads when each invocation referencesshared data. Calling a thread-safe function simultaneously with thesame data is safe, since all access to the shared data are serialized.

Most C++ member functions are inherently reentrant, since they onlyreference class member data. Any thread can call such a memberfunction on an instance, as long as no other thread is calling amember function on the same instance. For example, given the class Number below:

The methods Number::number() and Number::setNumber() arereentrant, since they only reference unique data. Only one thread ata time can call member functions on each instance of Number.However, multiple threads can call member functions on separateinstances of Number.

Thread-safe functions usually use a mutex (e.g a QMutex) to serializeaccess to shared data. Because of this, thread-safe functions areusually slower than reentrant functions, because of the extra overheadof locking and unlocking the mutex. For example, given the class Counter below:

Since the modifications of the static instances integer are notserialized, this class is not thread-safe. So make it threadsafe, amutex must be used:

Thread-safe Event Posting

In Qt, one thread is always the GUI or event thread. This is thethread that creates a QApplication object and callsQApplication::exec(). This is also the initial thread that callsmain() at program start. This thread is the only thread that isallowed to perform GUI operations, including generating and receivingevents from the window system. Qt does not support creatingQApplication and running the event loop (with QApplication::exec()) ina secondary thread. You must create the QApplication object and callQApplication::exec() from the main() function in your program.

Threads that wish to display data in a widget cannot modify the widgetdirectly, so they must post an event to the widget usingQApplication::postEvent(). The event will be delivered later on bythe GUI thread.

Normally, the programmer would like to include some information in theevent sent to the widget. See the documentation for QCustomEvent formore information on user-defined events.

Threads and QObject

Qt Execute Slot In Another Threaded

The QObject class itself is reentrant. However, certain rulesapply when creating and using QObjects in a thread that is not the GUIthread.

Set

Qt Execute Slot In Another Thread Rod

  1. None of the QObject based classes included in the Qt library arereentrant. This includes all widgets (e.g. QWidget andsubclasses), OS kernel classes (e.g. QProcess, QAccel, QTimer), andall networking classes (e.g. QSocket, QDns).
  2. QObject and all of its subclasses are notthread-safe. Thisincludes the entire event delivery system. It is important toremember that the GUI thread may be delivering events to your QObjectsubclass while you are accessing the object from another thread. Ifyou are using QObject in a thread that is not the GUI thread, and youare handling events sent to this object, you must protect allaccess to your data with a mutex; otherwise you may experience crashesor other undesired behavior.
  3. As a corollary to the above, deleting a QObject while pendingevents are waiting to be delivered can cause a crash. You must notdelete the QObject directly from a thread that is not the GUI thread.Use the QObject::deleteLater() method instead, which will cause theevent loop to delete the object after all pending events have beendelivered to the object.

The Qt Library Mutex

QApplication includes a mutex that is used to protect access to windowsystem functions. This mutex is locked while the event loop isrunning (e.g. during event delivery) and unlocked when the eventloopgoes to sleep. Note: The Qt event loop is recursive, and the librarymutex is not unlocked when re-entering the event loop (e.g. whenexecuting a modal dialog with QDialog::exec()).

If another thread locks the Qt library mutex, then the event loop willstop processing events, and the locking thread may do simple GUIoperations. Operations such as creating a QPainter and drawing a lineare examples of simple GUI operations:

Any operations that generate events must not be called by any threadother than the GUI thread. Examples of such operations are:

Slot
  • creating a QWidget, QTimer, QSocketNotifier, QSocket or other network class.
  • moving, resizing, showing or hiding a QWidget.
  • starting or stoping a QTimer.
  • enabling or disabling a QSocketNotifier.
  • using a QSocket or other network class.

Events generated by these operations will be lost on some platforms.

Qt Execute Slot In Another Thread Chart

Threads and Signals and Slots

The Signals and Slots mechanism can be used in separate threads, aslong as the rules for QObject based classes are followed. The Signalsand Slots mechanism is synchronous: when a signal is emitted, allslots are called immediately. The slots are executed in the threadcontext that emitted the signal.

Warning: Slots that generate window system events or use window systemfunctions mustnot be connected to a signal that is emitted froma thread that is not the GUI thread. See the Qt Library Mutex sectionabove for more details.

Threads and Shared Data

Qt provides many implicitly shared and explicitly shared classes. Ina multithreaded program, multiple instances of a shared class canreference shared data, which is dangerous if one or more threadsattempt to modify the data. Qt provides the QDeepCopy class, whichensures that shared classes reference unique data. See thedocumentation for more details.

Threads and the SQL Module

The classes in the SQL Module can be used in separate threads, as longas the rules for QObject based classes are followed.

The 3rd party libraries used by the QSqlDrivers can impose otherrestrictions on using the SQL Module in a multithreaded program. Forexample, the PostgreSQL library requires a separate connection perthread. Consult the documentation for your 3rd party library for moreinformation.

Caveats

Qt Execute Slot In Another Thread Size

Some things to watch out for when programming with threads:

Qt Execute Slot In Another Thread Pattern

  • As mentioned above, QObject based classes are neither thread-safenor reentrant. This includes all widgets (e.g. QWidget andsubclasses), OS kernel classes (e.g. QProcess, QAccel), and allnetworking classes (e.g. QSocket, QDns).
  • Deleting a QObject while pending events are waiting to be deliveredwill cause a crash. If you are creating QObjects in a thread that isnot the GUI thread and posting events to these objects, you should notdelete the QObject directly. Use the QObject::deleteLater() methodinstead, which will cause the event loop to delete the object afterall pending events have been delivered to the object.
  • Don't do any blocking operations while holding the Qt librarymutex. This will freeze up the event loop.
  • Make sure you unlock a recursive QMutex as many times as you lockit, no more and no less.
  • Don't mix the normal Qt library and the threaded Qt library in yourapplication. This means that if your application uses the threaded Qtlibrary, you should not link with the normal Qt library, dynamicallyload the normal Qt library or dynamically load another library orplugin that depends on the normal Qt library. On some systems, doingthis can corrupt the static data used in the Qt library.
  • Qt does not support creating QApplication and running the eventloop (with QApplication::exec()) in a secondary thread. You mustcreate the QApplication object and call QApplication::exec() from themain() function in your program.
Copyright © 2003TrolltechTrademarks