Sur cette page

Exécution simultanée

La fonction QtConcurrent::run() exécute une fonction dans un thread séparé. La valeur de retour de la fonction est disponible via l'API QFuture.

QtConcurrent::run() est une méthode surchargée. Vous pouvez considérer ces surcharges comme des modes légèrement différents. En mode basique, la fonction passée à QtConcurrent::run() est capable de rapporter un seul résultat de calcul à son appelant. En mode run with promise, la fonction passée à QtConcurrent::run() peut utiliser l'API supplémentaire QPromise, qui permet de rapporter des résultats multiples, des rapports de progression, de suspendre le calcul à la demande de l'appelant, ou d'arrêter le calcul à la demande de l'appelant.

Cette fonction fait partie du cadre Qt Concurrent.

Optimize comprend

Si vous incluez l'en-tête <QtConcurrent>, tout le module Qt Concurrent et tout le module Qt Core seront inclus, ce qui peut augmenter les temps de compilation et la taille des binaires. Pour utiliser la fonction QtConcurrent::run(), vous pouvez inclure un en-tête plus spécifique :

#include <QtConcurrentRun>

Exécution simultanée (mode de base)

La fonction passée à QtConcurrent::run() peut rapporter le résultat par sa valeur de retour.

Exécution d'une fonction dans un thread séparé

Pour exécuter une fonction dans un autre thread, utilisez QtConcurrent::run() :

extern void aFunction();
QFuture<void> future = QtConcurrent::run(aFunction);

Cela exécutera aFunction dans un thread séparé obtenu à partir du thread par défaut QThreadPool. Vous pouvez utiliser les classes QFuture et QFutureWatcher pour surveiller l'état de la fonction.

Pour utiliser un pool de threads dédié, vous pouvez passer QThreadPool comme premier argument :

extern void aFunction();
QThreadPool pool;
QFuture<void> future = QtConcurrent::run(&pool, aFunction);

Transmission d'arguments à la fonction

Le passage d'arguments à la fonction se fait en les ajoutant à l'appel de QtConcurrent::run() immédiatement après le nom de la fonction. Par exemple, l'appel à QtConcurrent::run()

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);

Une copie de chaque argument est effectuée au moment où QtConcurrent::run() est appelé, et ces valeurs sont transmises au thread lorsqu'il commence à exécuter la fonction. Les modifications apportées aux arguments après l'appel de QtConcurrent::run() ne sont pas visibles par le thread.

Notez que QtConcurrent::run ne permet pas d'appeler directement les fonctions surchargées. Par exemple, le code ci-dessous ne sera pas compilé :

void foo(int arg);
void foo(int arg1, int arg2);
...
QFuture<void> future = QtConcurrent::run(foo, 42);

La solution la plus simple consiste à appeler la fonction surchargée via lambda :

QFuture<void> future = QtConcurrent::run([] { foo(42); });

Ou vous pouvez indiquer au compilateur quelle surcharge choisir en utilisant static_cast:

QFuture<void> future = QtConcurrent::run(static_cast<void(*)(int)>(foo), 42);

ou qOverload:

QFuture<void> future = QtConcurrent::run(qOverload<int>(foo), 42);

Retourner les valeurs de la fonction

Toute valeur de retour de la fonction est disponible via QFuture:

extern QString functionReturningAString();
QFuture<QString> future = QtConcurrent::run(functionReturningAString);
...
QString result = future.result();

Si vous n'avez pas besoin du résultat (par exemple, parce que la fonction renvoie void), il est plus efficace d'utiliser la surcharge QThreadPool::start() en prenant un objet fonction.

Comme indiqué ci-dessus, le passage d'arguments se fait de la manière suivante :

extern QString someFunction(const QByteArray &input);

QByteArray bytearray = ...;

QFuture<QString> future = QtConcurrent::run(someFunction, bytearray);
...
QString result = future.result();

Notez que la fonction QFuture::result() se bloque et attend que le résultat soit disponible. Utilisez QFutureWatcher pour recevoir une notification lorsque l'exécution de la fonction est terminée et que le résultat est disponible.

Fonctionnalités supplémentaires de l'API

Utilisation des fonctions membres

QtConcurrent::run() accepte également les pointeurs vers les fonctions membres. Dans Qt 6, le premier argument doit être le pointeur de la fonction membre, suivi d'une référence const ou d'un pointeur sur une instance de la classe. Passer une référence const est utile pour appeler des fonctions membres const ; passer un pointeur est utile pour appeler des fonctions membres non const qui modifient l'instance.

Par exemple, l'appel de QByteArray::split() (une fonction membre const) dans un thread séparé se fait de la manière suivante :

// call 'QList<QByteArray>  QByteArray::split(char sep) const' in a separate thread
QByteArray bytearray = "hello world";
QFuture<QList<QByteArray> > future = QtConcurrent::run(&QByteArray::split, bytearray, ' ');
...
QList<QByteArray> result = future.result();

L'appel d'une fonction membre non-const se fait de la manière suivante :

// call 'void QImage::invertPixels(InvertMode mode)' in a separate thread
QImage image = ...;
QFuture<void> future = QtConcurrent::run(&QImage::invertPixels, &image, QImage::InvertRgba);
...
future.waitForFinished();
// At this point, the pixels in 'image' have been inverted

Utiliser les fonctions Lambda

L'appel d'une fonction lambda se fait comme suit :

QFuture<void> future = QtConcurrent::run([=]() {
    // Code in this block will run in another thread
});
...

L'appel d'une fonction qui modifie un objet passé par référence se fait comme suit :

static void addOne(int &n) { ++n; }
...
int n = 42;
QtConcurrent::run(&addOne, std::ref(n)).waitForFinished(); // n == 43

L'utilisation d'un objet appelable se fait comme suit :

struct TestClass
{
    void operator()(int s1) { s = s1; }
    int s = 42;
};

...

TestClass o;

// Modify original object
QtConcurrent::run(std::ref(o), 15).waitForFinished(); // o.s == 15

// Modify a copy of the original object
QtConcurrent::run(o, 42).waitForFinished(); // o.s == 15

// Use a temporary object
QtConcurrent::run(TestClass(), 42).waitForFinished();

// Ill-formed
QtConcurrent::run(&o, 42).waitForFinished(); // compilation error

Exécution simultanée avec promesse

Le mode Run With Promise permet plus de contrôle sur la tâche en cours d'exécution par rapport au mode de base de QtConcurrent::run(). Il permet de rapporter la progression de la tâche en cours, de rapporter des résultats multiples, de suspendre l'exécution si cela a été demandé, ou d'annuler la tâche à la demande de l'appelant.

L'argument obligatoire QPromise

La fonction passée à QtConcurrent::run() en mode Run With Promise doit avoir un argument supplémentaire de type QPromise<T> &, où T est le type du résultat du calcul (il doit correspondre au type T de QFuture<T> retourné par QtConcurrent::run()), comme par exemple :

extern void aFunction(QPromise<void> &promise);
QFuture<void> future = QtConcurrent::run(aFunction);

L'argument promise est instancié dans la fonction QtConcurrent::run(), et sa référence est passée à la fonction invoquée aFunction, de sorte que l'utilisateur n'a pas besoin de l'instancier, ni de le passer explicitement lorsqu'il appelle QtConcurrent::run() dans ce mode.

L'argument supplémentaire de type QPromise doit toujours apparaître comme premier argument dans la liste des arguments de la fonction, comme :

extern void aFunction(QPromise<void> &promise, int arg1, const QString &arg2);

int integer = ...;
QString string = ...;

QFuture<void> future = QtConcurrent::run(aFunction, integer, string);

Rapport des résultats

Contrairement au mode basique de QtConcurrent::run(), la fonction passée à QtConcurrent::run() en mode Run With Promise doit toujours retourner le type void. Le rapport de résultat est fait à travers l'argument supplémentaire de type QPromise. Cela permet également de rapporter des résultats multiples, comme par exemple :

void helloWorldFunction(QPromise<QString> &promise)
{
    promise.addResult("Hello");
    promise.addResult("world");
}

QFuture<QString> future = QtConcurrent::run(helloWorldFunction);
...
QList<QString> results = future.results();

Note : Il n'est pas nécessaire d'appeler QPromise::start() et QPromise::finish() pour indiquer le début et la fin du calcul (comme vous le feriez normalement en utilisant QPromise). QtConcurrent::run() les appellera toujours avant le début et après la fin de l'exécution.

Suspendre et annuler l'exécution

L'API QPromise permet également de suspendre et d'annuler le calcul, si nécessaire :

void aFunction(QPromise<int> &promise)
{
    for (int i = 0; i < 100; ++i) {
        promise.suspendIfRequested();
        if (promise.isCanceled())
            return;

        // computes the next result, may be time consuming like 1 second
        const int res = ... ;
        promise.addResult(res);
    }
}

QFuture<int> future = QtConcurrent::run(aFunction);

... // user pressed a pause button after 10 seconds
future.suspend();

... // user pressed a resume button after 10 seconds
future.resume();

... // user pressed a cancel button after 10 seconds
future.cancel();

L'appel à future.suspend() demande à la tâche en cours d'exécution de suspendre son exécution. Après avoir appelé cette méthode, la tâche en cours d'exécution sera suspendue après le prochain appel à promise.suspendIfRequested() dans sa boucle d'itération. Dans ce cas, la tâche en cours d'exécution se bloquera sur un appel à promise.suspendIfRequested(). L'appel bloqué se débloquera après l'appel à future.resume(). Notez qu'en interne, suspendIfRequested() utilise la condition d'attente pour débloquer, de sorte que le thread en cours d'exécution entre dans un état d'inactivité au lieu de gaspiller ses ressources lorsqu'il est bloqué afin de vérifier périodiquement si la demande de reprise provient du thread de l'appelant.

L'appel à future.cancel() de la dernière ligne fait que le prochain appel à promise.isCanceled() renvoie true et aFunction renvoie immédiatement sans autre rapport de résultat.

Remarque : il n'est pas nécessaire d'appeler QPromise::finish() pour arrêter le calcul après l'annulation (comme vous le feriez normalement en utilisant QPromise). QtConcurrent::run() l'appellera toujours après avoir terminé l'exécution.

Rapport d'avancement

Il est également possible de rapporter la progression d'une tâche indépendamment du rapport de résultat, comme par exemple :

void aFunction(QPromise<int> &promise) { promise.setProgressRange(0, 100) ; int result = 0; for(int i = 0; i < 100; ++i) { // calcule une partie de la tâche const int part = ...; result += part ; promise.setProgressValue(i) ; } promise.addResult(result) ; }QFutureWatcher<int> watcher ;QObject::connect(&watcher, &QFutureWatcher::progressValueChanged, [](int progress){ ...; // mise à jour de l'interface graphique avec une progression    qDebug() << "current progress:" << progress;
}) ; watcher.setFuture(QtConcurrent::run(aFunction)) ;

L'appelant installe le QFutureWatcher pour le QFuture retourné par QtConcurrent::run() afin de se connecter à son signal progressValueChanged() et de mettre à jour, par exemple, l'interface utilisateur graphique en conséquence.

Invoquer des fonctions avec un opérateur surchargé()()

Par défaut, QtConcurrent::run() ne supporte pas les foncteurs avec des operator()() surchargés en mode Run With Promise. Dans le cas des foncteurs surchargés, l'utilisateur doit explicitement spécifier le type de résultat en tant que paramètre de modèle passé à QtConcurrent::run(), comme :

struct Functor {
    void operator()(QPromise<int> &) { }
    void operator()(QPromise<double> &) { }
};

Functor f;
run<double>(f); // this will select the 2nd overload
// run(f);      // error, both candidate overloads potentially match

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.