Viadeo Twitter Google Bookmarks ! Facebook Digg del.icio.us MySpace Yahoo MyWeb Blinklist Netvouz Reddit Simpy StumbleUpon Bookmarks Windows Live Favorites 
Logo Documentation Qt ·  Page d'accueil  ·  Toutes les classes  ·  Classes principales  ·  Annotées  ·  Classes groupées  ·  Fonctions  · 

Thread Support in Qt

Introduction

Qt provides thread support in the form of basic platform-independent threading classes, a thread-safe way of posting events, and a global Qt library lock that allows you to call Qt methods from different threads.

This document is intended for an audience that has knowledge of, and experience with, multithreaded applications. If you are new to threading see our Recommended Reading list.

Enabling Thread Support

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

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

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 an entry 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 begins execution in your reimplementation of QThread::run(). This is similar to the Java thread class.

  • QThreadStorage - Provides per-thread data storage. This class can only be used with threads started with QThread; it cannot be used with threads started with platform-specific APIs.

  • QMutex - Provides a mutual exclusion lock (also know as a mutex).
  • QMutexLocker - A convenience class which automatically locks and unlocks a QMutex. QMutexLocker is useful in complicated code, or in code which uses exceptions. See the documentation for more details.
  • QWaitCondition - Provides a way for threads to go to sleep until woken up by another thread.
  • QSemaphore - Provides a simple integer semaphore.

Important Definitions

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

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

Note that Qt provides both implictly and explicitly shared classes. For more information, see the Threads and Shared Data section.

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

    class Number
    {
    public:
        inline Number( int n ) : num( n ) { }

        inline int number() const { return num; }
        inline void setNumber( int n ) { num = n; }

    private:
        int num;
    };

The methods Number::number() and Number::setNumber() are reentrant, since they only reference unique data. Only one thread at a time can call member functions on each instance of Number. However, multiple threads can call member functions on separate instances of Number.

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

    class Counter
    {
    public:
        inline Counter()  { ++instances; }
        inline ~Counter() { --instances; }

    private:
        static int instances;
    };

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

    class Counter
    {
    public:
        inline Counter()
        {
            mutex.lock();
            ++instances;
            mutex.unlock();
        }

        ...
    private:
        static QMutex mutex;
        static int instances;
    };

Thread-safe Event Posting

In Qt, one thread is always the GUI or event thread. This is the thread that creates a QApplication object and calls QApplication::exec(). This is also the initial thread that calls main() at program start. This thread is the only thread that is allowed to perform GUI operations, including generating and receiving events from the window system. Qt does not support creating QApplication and running the event loop (with QApplication::exec()) in a secondary thread. You must create the QApplication object and call QApplication::exec() from the main() function in your program.

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

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

Threads and QObject subclasses

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

  1. None of the QObject based classes included in the Qt library are reentrant. This includes all widgets (e.g. QWidget and subclasses), OS kernel classes (e.g. QProcess, QAccel, QTimer), and all networking classes (e.g. QSocket, QDns).

  2. QObject and all of its subclasses are not thread-safe. This includes the entire event delivery system. It is important to remember that the GUI thread may be delivering events to your QObject subclass while you are accessing the object from another thread. If you are using QObject in a thread that is not the GUI thread, and you are handling events sent to this object, you must protect all access to your data with a mutex; otherwise you may experience crashes or other undesired behavior.

  3. As a corollary to the above, deleting a QObject while pending events are waiting to be delivered can cause a crash. You must not delete the QObject directly from a thread that is not the GUI thread. Use the QObject::deleteLater() method instead, which will cause the event loop to delete the object after all pending events have been delivered to the object.

The Qt Library Mutex

QApplication includes a mutex that is used to protect access to window system functions. This mutex is locked while the event loop is running (e.g. during event delivery) and unlocked when the eventloop goes to sleep. Note: The Qt event loop is recursive, and the library mutex is not unlocked when re-entering the event loop (e.g. when executing a modal dialog with QDialog::exec()).

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

    ...
    qApp->lock();

    QPainter p;
    p.begin( mywidget );
    p.setPen( QColor( "red" ) );
    p.drawLine( 0,0,100,100 );
    p.end();

    qApp->unlock();
    ...

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

  • 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.

Threads and Signals and Slots

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

Warning: Slots that generate window system events or use window system functions must not be connected to a signal that is emitted from a thread that is not the GUI thread. See the Qt Library Mutex section above for more details.

Threads and Shared Data

Qt provides many implicitly shared and explicitly shared classes. In a multithreaded program, multiple instances of a shared class can reference shared data, which is dangerous if one or more threads attempt to modify the data. Qt provides the QDeepCopy class, which ensures that shared classes reference unique data.

See the description of implicit sharing for more information.

Threads and the SQL Module

A connection can only be used from within the thread that created it. Moving connections between threads or creating queries from a different thread is not supported.

In addition, the third party libraries used by the QSqlDrivers can impose further restrictions on using the SQL Module in a multithreaded program. Consult the manual of your database client for more information.

Caveats

Some things to watch out for when programming with threads:

  • As mentioned above, QObject based classes are neither thread-safe nor reentrant. This includes all widgets (e.g. QWidget and subclasses), OS kernel classes (e.g. QProcess, QAccel), and all networking classes (e.g. QSocket, QDns).

  • Deleting a QObject while pending events are waiting to be delivered will cause a crash. If you are creating QObjects in a thread that is not the GUI thread and posting events to these objects, you should not delete the QObject directly. Use the QObject::deleteLater() method instead, which will cause the event loop to delete the object after all pending events have been delivered to the object.

  • Don't do any blocking operations while holding the Qt library mutex. This will freeze up the event loop.

  • Make sure you unlock a recursive QMutex as many times as you lock it, no more and no less.

  • Don't mix the normal Qt library and the threaded Qt library in your application. This means that if your application uses the threaded Qt library, you should not link with the normal Qt library, dynamically load the normal Qt library or dynamically load another library or plugin that depends on the normal Qt library. On some systems, doing this can corrupt the static data used in the Qt library.

  • Qt does not support creating QApplication and running the event loop (with QApplication::exec()) in a secondary thread. You must create the QApplication object and call QApplication::exec() from the main() function in your program.

Recommended Reading

Publicité

Best Of

Actualités les plus lues

Semaine
Mois
Année
  1. Microsoft ouvre aux autres compilateurs C++ AMP, la spécification pour la conception d'applications parallèles C++ utilisant le GPU 22
  2. Les développeurs ignorent-ils trop les failles découvertes dans leur code ? Prenez-vous en compte les remarques des autres ? 17
  3. RIM : « 13 % des développeurs ont gagné plus de 100 000 $ sur l'AppWord », Qt et open-source au menu du BlackBerry DevCon Europe 0
  4. « Quelque chose ne va vraiment pas avec les développeurs "modernes" », un développeur à "l'ancienne" critique la multiplication des bibliothèques 12
  5. BlackBerry 10 : premières images du prochain OS de RIM qui devrait intégrer des widgets et des tuiles inspirées de Windows Phone 0
  6. Adieu qmake, bienvenue qbs : Qt Building Suite, un outil déclaratif et extensible pour la compilation de projets Qt 17
  7. Quelles nouveautés de C++11 Visual C++ doit-il rapidement intégrer ? Donnez-nous votre avis 10
Page suivante

Le Qt Developer Network au hasard

Logo

Applications mobiles modernes avec Qt et QML

Le Qt Developer Network est un réseau de développeurs Qt anglophone, où ils peuvent partager leur expérience sur le framework. Lire l'article.

Communauté

Ressources

Liens utiles

Contact

  • Vous souhaitez rejoindre la rédaction ou proposer un tutoriel, une traduction, une question... ? Postez dans le forum Contribuez ou contactez-nous par MP ou par email (voir en bas de page).

Qt dans le magazine

Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia. Qt 3.3
Copyright © 2012 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vous avez déniché une erreur ? Un bug ? Une redirection cassée ? Ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter ou par MP !
 
 
 
 
Partenaires

Hébergement Web