QFuture Class
template <typename T> class QFutureLa classe QFuture représente le résultat d'un calcul asynchrone. Plus d'informations...
| En-tête : | #include <QFuture> |
| CMake : | find_package(Qt6 REQUIRED COMPONENTS Core)target_link_libraries(mytarget PRIVATE Qt6::Core) |
| qmake : | QT += core |
- Liste de tous les membres, y compris les membres hérités
- Les membres dépréciés
- QFuture fait partie de Threading Classes.
Note : Toutes les fonctions de cette classe sont sûres pour les threads, à l'exception des fonctions suivantes :
Types publics
| class | const_iterator |
| ConstIterator |
Fonctions publiques
| QFuture() | |
| QFuture(const QFuture<T> &other) | |
| ~QFuture() | |
| QFuture<T>::const_iterator | begin() const |
| void | cancel() |
(since 6.10) void | cancelChain() |
| QFuture<T>::const_iterator | constBegin() const |
| QFuture<T>::const_iterator | constEnd() const |
| QFuture<T>::const_iterator | end() const |
| bool | isCanceled() const |
| bool | isFinished() const |
| bool | isResultReadyAt(int index) const |
| bool | isRunning() const |
| bool | isStarted() const |
(since 6.0) bool | isSuspended() const |
(since 6.0) bool | isSuspending() const |
(since 6.0) bool | isValid() const |
(since 6.0) QFuture<T> | onCanceled(Function &&handler) |
(since 6.1) QFuture<T> | onCanceled(QObject *context, Function &&handler) |
(since 6.0) QFuture<T> | onFailed(Function &&handler) |
(since 6.1) QFuture<T> | onFailed(QObject *context, Function &&handler) |
| int | progressMaximum() const |
| int | progressMinimum() const |
| QString | progressText() const |
| int | progressValue() const |
| T | result() const |
| T | resultAt(int index) const |
| int | resultCount() const |
| QList<T> | results() const |
| void | resume() |
(since 6.0) void | setSuspended(bool suspend) |
(since 6.0) void | suspend() |
(since 6.0) T | takeResult() |
(since 6.0) QFuture<QFuture<T>::ResultType<Function>> | then(Function &&function) |
(since 6.1) QFuture<QFuture<T>::ResultType<Function>> | then(QObject *context, Function &&function) |
(since 6.0) QFuture<QFuture<T>::ResultType<Function>> | then(QThreadPool *pool, Function &&function) |
(since 6.0) QFuture<QFuture<T>::ResultType<Function>> | then(QtFuture::Launch policy, Function &&function) |
(since 6.0) void | toggleSuspended() |
(since 6.4) QFuture<U> | unwrap() |
| void | waitForFinished() |
| QFuture<T> & | operator=(const QFuture<T> &other) |
Description détaillée
QFuture permet aux threads d'être synchronisés avec un ou plusieurs résultats qui seront prêts à un moment ultérieur. Le résultat peut être de n'importe quel type ayant des constructeurs par défaut, par copie et éventuellement par déplacement. Si un résultat n'est pas disponible au moment de l'appel des fonctions result(), resultAt(), results() et takeResult(), QFuture attendra que le résultat devienne disponible. Vous pouvez utiliser la fonction isResultReadyAt() pour déterminer si un résultat est prêt ou non. Pour les objets QFuture qui rapportent plus d'un résultat, la fonction resultCount() renvoie le nombre de résultats continus. Cela signifie qu'il est toujours sûr d'itérer à travers les résultats de 0 à resultCount(). takeResult() invalide un futur, et toute tentative ultérieure d'accéder au résultat ou aux résultats du futur entraîne un comportement indéfini. isValid() indique si les résultats sont accessibles.
QFuture fournit un itérateur de style Java (QFutureIterator) et un itérateur de style STL (QFuture::const_iterator). L'utilisation de ces itérateurs est un autre moyen d'accéder aux résultats dans le futur.
Si le résultat d'un calcul asynchrone doit être transmis à un autre, QFuture fournit un moyen pratique d'enchaîner plusieurs calculs séquentiels en utilisant then(). onCanceled() peut être utilisé pour ajouter un gestionnaire à appeler si le QFuture est annulé. En outre, onFailed() peut être utilisé pour gérer les échecs survenus dans la chaîne. Notez que QFuture s'appuie sur les exceptions pour la gestion des erreurs. Si l'utilisation d'exceptions n'est pas envisageable, vous pouvez toujours indiquer l'état d'erreur de QFuture en intégrant le type d'erreur dans le type QFuture. Par exemple, vous pouvez utiliser std::variant, std::any ou similaire pour conserver le résultat ou l'échec ou créer votre propre type.
L'exemple ci-dessous montre comment la gestion des erreurs peut être effectuée sans utiliser d'exceptions. Supposons que nous voulions envoyer une requête réseau pour obtenir un fichier volumineux à partir d'un emplacement réseau. Nous voulons ensuite l'écrire dans le système de fichiers et renvoyer son emplacement en cas de succès. Ces deux opérations peuvent échouer avec différentes erreurs. Nous utilisons donc std::variant pour conserver le résultat ou l'erreur :
using NetworkReply = std::variant<QByteArray, QNetworkReply::NetworkError>; enum class IOError { FailedToRead, FailedToWrite }; using IOResult = std::variant<QString, IOError>;
Et nous combinons les deux opérations en utilisant then() :
QFuture<IOResult> future = QtConcurrent::run([url] { //... return NetworkReply(QNetworkReply::TimeoutError); }).then([](NetworkReply reply) { if (auto error = std::get_if<QNetworkReply::NetworkError>(&reply)) return IOResult(IOError::FailedToRead); auto data = std::get_if<QByteArray>(&reply); // try to write *data and return IOError::FailedToWrite on failure //... }); auto result = future.result(); if (auto filePath = std::get_if<QString>(&result)) { // do something with *filePath } else { // process the error }
Il est possible d'enchaîner plusieurs continuations et gestionnaires dans n'importe quel ordre. Il est possible d'enchaîner plusieurs continuations et gestionnaires dans n'importe quel ordre :
QFuture<int> testFuture = someIntFuture; auto resultFuture = testFuture.then([](int res) { // Block 1 }).onCanceled([] { // Block 2 }).onFailed([] { // Block 3 }).then([] { // Block 4 }).onFailed([] { // Block 5 }).onCanceled([] { // Block 6 });
En fonction de l'état de testFuture (annulé, a une exception ou a un résultat), le prochain onCanceled(), onFailed() ou then() sera appelé. Ainsi, si testFuture est exécuté avec succès, Block 1 sera appelé. S'il réussit également, le prochain then() (Block 4) est appelé. Si testFuture est annulé ou échoue avec une exception, Block 2 ou Block 3 sera appelé respectivement. Le prochain then() sera appelé ensuite, et l'histoire se répète.
Remarque : si Block 2 est invoqué et qu'il soulève une exception, l'appel suivant onFailed() (Block 3) la traitera. Si l'ordre de onFailed() et onCanceled() était inversé, l'état d'exception se propagerait aux continuations suivantes et serait finalement capturé dans Block 5.
Dans l'exemple suivant, le premier onCanceled() (Block 2) est supprimé :
QFuture<int> testFuture = someIntFuture; auto resultFuture = testFuture.then([](int res) { // Block 1 }).onFailed([] { // Block 3 }).then([] { // Block 4 }).onFailed([] { // Block 5 }).onCanceled([] { // Block 6 });
Si testFuture est annulé, son état est propagé au prochain then(), qui sera également annulé. Dans ce cas, c'est donc Block 6 qui sera appelé.
Le futur ne peut avoir qu'une seule suite. Prenons l'exemple suivant :
QPromise<int> p; QFuture<int> f1 = p.future(); f1.then([](int) { qDebug("first"); }); QFuture<int> f2 = p.future(); f2.then([](int) { qDebug("second"); }); p.start(); p.addResult(42); p.finish();
Dans ce cas, f1 et f2 sont effectivement le même objet QFuture, car ils partagent le même état interne. Par conséquent, l'appel de then sur f2 écrasera la suite spécifiée pour f1. Ainsi, seul "second" sera imprimé lors de l'exécution de ce code.
QFuture offre également des moyens d'interagir avec un calcul en cours d'exécution. Par exemple, le calcul peut être annulé avec la fonction cancel(). Pour suspendre ou reprendre le calcul, utilisez la fonction setSuspended() ou l'une des fonctions de commodité suspend(), resume() ou toggleSuspended(). Sachez que tous les calculs asynchrones en cours d'exécution ne peuvent pas être annulés ou suspendus. Par exemple, le futur retourné par QtConcurrent::run() ne peut pas être annulé, mais le futur retourné par QtConcurrent::mappedReduced() peut l'être.
Les informations sur la progression sont fournies par les fonctions progressValue(), progressMinimum(), progressMaximum() et progressText(). La fonction waitForFinished() bloque le thread appelant et attend que le calcul se termine, garantissant ainsi que tous les résultats sont disponibles.
L'état du calcul représenté par une QFuture peut être interrogé à l'aide des fonctions isCanceled(), isStarted(), isFinished(), isRunning(), isSuspending() ou isSuspended().
QFuture<void> est spécialisé pour ne contenir aucune des fonctions de récupération des résultats. Tout QFuture<T> peut être assigné ou copié dans un QFuture<void> également. Cela est utile si l'on a besoin uniquement d'informations sur l'état ou la progression de la tâche, et non des données de résultat proprement dites.
Pour interagir avec des tâches en cours d'exécution à l'aide de signaux et de slots, utilisez QFutureWatcher.
Vous pouvez également utiliser QtFuture::connect() pour connecter des signaux à un objet QFuture qui sera résolu lorsqu'un signal sera émis. Cela permet de travailler avec des signaux comme avec des objets QFuture. Par exemple, si vous le combinez avec then(), vous pouvez attacher plusieurs continuations à un signal, qui sont invoquées dans le même thread ou dans un nouveau thread.
Les fonctions QtFuture::whenAll() et QtFuture::whenAny() peuvent être utilisées pour combiner plusieurs futures et suivre la fin de la dernière ou de la première d'entre elles.
Un objet QFuture prêt avec une valeur ou un objet QFuture contenant une exception peut être créé à l'aide des fonctions de commodité QtFuture::makeReadyVoidFuture(), QtFuture::makeReadyValueFuture(), QtFuture::makeReadyRangeFuture() et QtFuture::makeExceptionalFuture().
Remarque : certaines API (voir QFuture::then() ou diverses surcharges de la méthode QtConcurrent ) permettent de planifier le calcul dans un pool de threads spécifique. Cependant, QFuture met en œuvre un algorithme de vol de travail pour éviter les blocages et optimiser l'utilisation des threads. Par conséquent, les calculs peuvent être exécutés directement dans le thread qui demande le résultat de QFuture.
Remarque : pour lancer un calcul et stocker les résultats dans une QFuture, utilisez QPromise ou l'une des API du framework Qt Concurrent du cadre de QFuture.
Voir également QPromise, QtFuture::connect(), QtFuture::makeReadyVoidFuture(), QtFuture::makeReadyValueFuture(), QtFuture::makeReadyRangeFuture(), QtFuture::makeExceptionalFuture(), QFutureWatcher, et Qt Concurrent.
Documentation sur les types de membres
QFuture::ConstIterator
Synonyme de style Qt pour QFuture::const_iterator.
Documentation des fonctions membres
QFuture::QFuture()
Construit un futur vide et annulé.
QFuture::QFuture(const QFuture<T> &other)
Construit une copie de other.
Voir aussi operator=().
QFuture::~QFuture()
Détruit le futur.
Notez que cela n'attend pas et n'annule pas le calcul asynchrone. Utilisez waitForFinished() ou QFutureSynchronizer lorsque vous devez vous assurer que le calcul est terminé avant que le futur ne soit détruit.
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::begin() const
Renvoie un itérateur constant de style STL pointant vers le premier résultat dans le futur.
Voir aussi constBegin() et end().
void QFuture::cancel()
Annule le calcul asynchrone représenté par ce futur. Notez que l'annulation est asynchrone. Utilisez waitForFinished() après avoir appelé cancel() si vous avez besoin d'une annulation synchrone.
Les résultats actuellement disponibles peuvent toujours être consultés sur un futur annulé, mais les nouveaux résultats ne seront pas disponibles après l'appel à cette fonction. Tout objet QFutureWatcher qui surveille ce futur ne fournira pas de signaux de progression et de résultats prêts sur un futur annulé.
Il faut savoir que tous les calculs asynchrones en cours d'exécution ne peuvent pas être annulés. Par exemple, le futur retourné par QtConcurrent::run() ne peut pas être annulé, mais le futur retourné par QtConcurrent::mappedReduced() peut l'être.
Voir aussi cancelChain().
[since 6.10] void QFuture::cancelChain()
Annule l'ensemble de la chaîne de continuation. Tous les futures déjà terminés restent inchangés et leurs résultats sont toujours disponibles. Chaque continuation en attente est annulée et son gestionnaire onCanceled() est appelé, s'il existe dans la chaîne de continuation.
auto f = QtConcurrent::run([] {/*...*/}) .then([]{ // Then 1 }) .then([]{ // Then 2 }) .onCanceled([]{ // OnCanceled 1 }) .then([]{ // Then 3 }) .then([]{ // Then 4 }) .onCanceled([]{ // OnCanceled 2 }); //... f.cancelChain();
Dans l'exemple, si la chaîne est annulée avant l'exécution de la suite Then 2, les gestionnaires d'annulation OnCanceled 1 et OnCanceled 2 seront invoqués.
Si la chaîne est annulée après Then 2, mais avant Then 4, seul OnCanceled 2 sera invoqué.
Remarque : lorsqu'elle est appelée sur un futur déjà terminé, cette méthode n'a aucun effet. Il est recommandé de l'utiliser sur l'objet QFuture qui représente l'ensemble de la chaîne de continuation, comme indiqué dans l'exemple ci-dessus.
Si l'une des continuations de la chaîne exécute un calcul asynchrone et renvoie un objet QFuture le représentant, l'appel à cancelChain() ne sera pas propagé dans ce calcul imbriqué une fois qu'il aura démarré. La raison en est que le futur ne sera disponible dans la chaîne de continuation que lorsque le futur extérieur sera exécuté, mais l'annulation peut se produire lorsqu'un futur extérieur et un futur imbriqué attendent toujours que leurs calculs soient terminés. Dans ce cas, le futur imbriqué doit être capturé et annulé explicitement.
QFuture<void> nested; auto f = createFuture() .then([&]{ nested = runNestedComputation(); // do some other work return nested; }) .unwrap() .then([]{ // other continuation }) .onCanceled([]{ // handle cancellation }); //... f.cancelChain(); nested.cancel();
Dans cet exemple, si runNestedComputation() est déjà en cours, il ne peut être annulé qu'en appelant nested.cancel().
Cette fonction a été introduite dans Qt 6.10.
Voir aussi cancel().
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::constBegin() const
Renvoie un itérateur constant de style STL pointant vers le premier résultat dans le futur.
Voir aussi begin() et constEnd().
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::constEnd() const
Renvoie un itérateur constant de style STL pointant vers le résultat imaginaire après le dernier résultat dans le futur.
Voir aussi constBegin() et end().
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::end() const
Renvoie un itérateur constant de style STL pointant vers le résultat imaginaire après le dernier résultat dans le futur.
Voir aussi begin() et constEnd().
bool QFuture::isCanceled() const
Renvoie true si le calcul asynchrone a été annulé avec la fonction cancel() ; sinon, renvoie false.
Sachez que le calcul peut toujours être en cours d'exécution même si cette fonction renvoie true. Voir cancel() pour plus de détails.
bool QFuture::isFinished() const
Renvoie true si le calcul asynchrone représenté par ce futur est terminé, sinon renvoie false.
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> bool QFuture::isResultReadyAt(int index) const
Renvoie true si le résultat de index est immédiatement disponible ; sinon, renvoie false.
Remarque : l'appel de cette fonction entraîne un comportement indéfini si isValid() renvoie false pour ce QFuture. Si QFuture n'est pas encore lancé, appelez waitForFinished() avant d'appeler cette fonction pour éviter un comportement indéfini.
Voir aussi resultAt(), resultCount() et takeResult().
bool QFuture::isRunning() const
Renvoie true si le calcul asynchrone représenté par ce futur est en cours d'exécution ; sinon, renvoie false.
bool QFuture::isStarted() const
Renvoie true si le calcul asynchrone représenté par ce futur a été lancé ; sinon, renvoie false.
[since 6.0] bool QFuture::isSuspended() const
Renvoie true si une suspension du calcul asynchrone a été demandée et qu'elle est effective, ce qui signifie que plus aucun résultat ou changement de progression n'est attendu.
Cette fonction a été introduite dans Qt 6.0.
Voir aussi setSuspended(), toggleSuspended(), et isSuspending().
[since 6.0] bool QFuture::isSuspending() const
Renvoie true si le calcul asynchrone a été suspendu avec la fonction suspend(), mais que le travail n'est pas encore suspendu et que le calcul est toujours en cours. Retourne false dans le cas contraire.
Pour vérifier si la suspension est effective, utilisez plutôt isSuspended().
Cette fonction a été introduite dans Qt 6.0.
Voir aussi setSuspended(), toggleSuspended(), et isSuspended().
[since 6.0] bool QFuture::isValid() const
Renvoie true si un ou plusieurs résultats peuvent être obtenus à partir de cet objet QFuture. Renvoie false si l'activité connexe QPromise n'a pas encore commencé ou si le résultat a déjà été collecté dans le futur.
Remarque : la valeur de retour de cette fonction indique uniquement si le résultat futur peut être consommé, et non s'il est prêt. Cette fonction renverra true lorsque la fonction connexe QPromise est lancée, mais que le résultat n'est pas encore prêt. Pour vérifier si le résultat est prêt, appelez isResultReadyAt() ou isFinished().
Cette fonction a été introduite dans Qt 6.0.
Voir aussi takeResult(), result(), results(), resultAt(), isFinished() et isResultReadyAt().
[since 6.0] template <typename Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>> QFuture<T> QFuture::onCanceled(Function &&handler)
Attache une annulation handler à ce futur. Le futur retourné se comporte exactement comme ce futur (il a le même état et le même résultat) à moins que ce futur ne soit annulé. Le handler est un appelable qui ne prend aucun argument et renvoie une valeur du type emballé par ce futur. Après l'annulation, le futur retourné empaquette la valeur retournée par handler.
S'il est attaché avant l'annulation, handler sera invoqué dans le même thread que celui qui signale que le futur est terminé après l'annulation. Si le gestionnaire est attaché après que ce futur a déjà été annulé, il sera invoqué immédiatement dans le thread qui exécute onCanceled(). Par conséquent, le gestionnaire ne peut pas toujours supposer sur quel thread il sera exécuté. Utilisez la surcharge qui prend un objet de contexte si vous voulez contrôler sur quel thread le gestionnaire est invoqué.
L'exemple ci-dessous montre comment attacher un gestionnaire d'annulation :
QFuture<int> testFuture /*...*/; auto resultFuture = testFuture.then([](int res) { // Block 1 //... return 1; }).then([](int res) { // Block 2 //... return 2; }).onCanceled([] { // Block 3 //... return -1; });
Si testFuture est annulé, Block 3 sera appelé et resultFuture aura pour résultat -1. Contrairement à testFuture, il ne sera pas dans l'état Canceled. Cela signifie que vous pouvez obtenir son résultat, y attacher des countinuations, etc.
Notez également que vous pouvez annuler la chaîne de continuations pendant qu'elles s'exécutent via le futur qui a démarré la chaîne. Disons que testFuture.cancel() a été appelé alors que Block 1 est déjà en cours d'exécution. La continuation suivante détectera que l'annulation a été demandée, de sorte que Block 2 sera ignoré et que le gestionnaire d'annulation (Block 3) sera appelé.
Remarque : cette méthode renvoie un nouveau QFuture représentant le résultat de la chaîne de continuation. L'annulation de l'adresse QFuture elle-même n'entraînera pas l'appel au gestionnaire d'annulation de la chaîne qui l'a précédée. Cela signifie que si vous appelez resultFuture.cancel(), Block 3 ne sera pas appelé : parce que resultFuture est le futur qui résulte de l'attachement du gestionnaire d'annulation à testFuture, aucun gestionnaire d'annulation n'a été attaché à resultFuture lui-même. Seule l'annulation de testFuture ou des futurs renvoyés par les continuations attachées avant l'appel de onCancelled() peut déclencher Block 3.
Cette fonction a été introduite dans Qt 6.0.
Voir aussi then() et onFailed().
[since 6.1] template <typename Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>> QFuture<T> QFuture::onCanceled(QObject *context, Function &&handler)
Attache une annulation handler à ce future, qui sera appelée lorsque le future sera annulé. Le handler est un appelable qui ne prend aucun argument. Il sera invoqué dans le thread de l'objet context. Cela peut être utile si l'annulation doit être gérée dans un thread spécifique.
Si l'objet context est détruit avant la fin de la chaîne, le futur est annulé. Voir then() pour plus de détails.
Remarque : lors de l'appel de cette méthode, il convient de s'assurer que le context reste en vie pendant la configuration de la chaîne.
Voir la documentation de l'autre surcharge pour plus de détails sur handler.
Il s'agit d'une fonction surchargée.
Cette fonction a été introduite dans Qt 6.1.
Voir aussi then() et onFailed().
[since 6.0] template <typename Function, typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>> QFuture<T> QFuture::onFailed(Function &&handler)
Attache un gestionnaire d'échec à ce futur, pour gérer les exceptions. Le futur retourné se comporte exactement comme ce futur (il a le même état et le même résultat) à moins que ce futur n'échoue avec une exception.
Le handler est un appelable qui ne prend aucun argument ou un argument, pour filtrer les types d'erreurs spécifiques, similaire à l'instruction catch. Il renvoie une valeur du type emballé par ce futur. Après l'échec, le futur retourné empaquette la valeur retournée par handler.
Le gestionnaire ne sera invoqué que si une exception est levée. Si l'exception est soulevée après que ce gestionnaire ait été attaché, le gestionnaire est exécuté dans le thread qui signale que le futur est terminé à la suite de l'exception. Si le gestionnaire est attaché après que ce futur a déjà échoué, il sera invoqué immédiatement, dans le thread qui exécute onFailed(). Par conséquent, le gestionnaire ne peut pas toujours supposer sur quel thread il sera exécuté. Utilisez la surcharge qui prend un objet de contexte si vous voulez contrôler sur quel thread le gestionnaire est invoqué.
L'exemple ci-dessous montre comment attacher un gestionnaire d'échec :
QFuture<int> future = someIntFuture; auto resultFuture = future.then([](int res) { //... throw Error(); //... return res; }).onFailed([](const Error &e) { // Handle exceptions of type Error //... return -1; }).onFailed([] { // Handle all other types of errors //... return -1; }); auto result = resultFuture.result(); // result is -1
Si plusieurs gestionnaires sont attachés, le premier gestionnaire qui correspond au type d'exception lancé sera invoqué. Par exemple, si aucun des gestionnaires ne correspond au type d'exception lancé, le premier gestionnaire sera invoqué :
QFuture<int> future = someIntFuture; future.then([](int res) { //... throw std::runtime_error("message"); //... }).onFailed([](const std::exception &e) { // This handler will be invoked return -1; }).onFailed([](const std::runtime_error &e) { // This handler won't be invoked, because of the handler above. return -1; });
Si aucun des gestionnaires ne correspond au type d'exception lancé, l'exception sera propagée au futur résultant :
QFuture<int> future = someIntFuture; auto resultFuture = future.then([](int res) { //... throw Error("message"); //... return res; }).onFailed([](const std::exception &e) { // Won't be invoked return -1; }).onFailed([](const QException &e) { // Won't be invoked return -1; }); try { auto result = resultFuture.result(); } catch(QException &someException) { // Handle the exception }
Note : Vous pouvez toujours attacher un gestionnaire ne prenant aucun argument, pour gérer tous les types d'exception et éviter d'écrire le bloc try-catch.
Cette fonction a été introduite dans Qt 6.0.
Voir aussi then() et onCanceled().
[since 6.1] template <typename Function, typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>> QFuture<T> QFuture::onFailed(QObject *context, Function &&handler)
Attache un gestionnaire d'échec à ce futur, pour gérer toutes les exceptions que le futur soulève, ou qu'il a déjà soulevées. Retourne un QFuture du même type que ce futur. Le gestionnaire ne sera invoqué qu'en cas d'exception, dans le thread de l'objet context. Cela peut être utile si l'échec doit être traité dans un thread spécifique. Par exemple :
// somewhere in the main thread auto future = QtConcurrent::run([] { // This will run in a separate thread //... throw std::exception(); }).onFailed(this, [] { // Update UI elements });
Le gestionnaire d'échec attaché à QtConcurrent::run met à jour les éléments de l'interface utilisateur et ne peut pas être invoqué à partir d'un fil d'exécution autre que celui de l'interface utilisateur. Ainsi, this est fourni comme contexte à .onFailed(), pour s'assurer qu'il sera invoqué dans le fil d'exécution principal.
Si context est détruit avant la fin de la chaîne, le futur est annulé. Voir then() pour plus de détails.
Remarque : lors de l'appel de cette méthode, il convient de s'assurer que le context reste en vie pendant la configuration de la chaîne.
Voir la documentation de l'autre surcharge pour plus de détails sur handler.
Il s'agit d'une fonction surchargée.
Cette fonction a été introduite dans Qt 6.1.
Voir aussi then() et onCanceled().
int QFuture::progressMaximum() const
Renvoie le maximum de progressValue().
Voir aussi progressValue() et progressMinimum().
int QFuture::progressMinimum() const
Renvoie le minimum progressValue().
Voir aussi progressValue() et progressMaximum().
QString QFuture::progressText() const
Renvoie la représentation textuelle (facultative) de la progression telle qu'elle est rapportée par le calcul asynchrone.
Attention, tous les calculs ne fournissent pas une représentation textuelle de la progression, et cette fonction peut donc renvoyer une chaîne vide.
int QFuture::progressValue() const
Renvoie la valeur actuelle de la progression, qui se situe entre progressMinimum() et progressMaximum().
Voir aussi progressMinimum() et progressMaximum().
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::result() const
Renvoie le premier résultat dans le futur. Si le résultat n'est pas immédiatement disponible, cette fonction se bloque et attend que le résultat soit disponible. Il s'agit d'une méthode pratique pour appeler resultAt(0). Notez que result() renvoie une copie du résultat stocké en interne. Si T est un type à déplacement uniquement, ou si vous ne souhaitez pas copier le résultat, utilisez takeResult() à la place.
Remarque : l'appel à cette fonction entraîne un comportement indéfini si isValid() renvoie false pour ce QFuture. Si QFuture n'est pas encore lancé, appelez waitForFinished() avant d'appeler cette fonction pour éviter un comportement indéfini.
Voir aussi resultAt(), results() et takeResult().
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::resultAt(int index) const
Renvoie le résultat à index dans le futur. Si le résultat n'est pas immédiatement disponible, cette fonction se bloque et attend que le résultat soit disponible.
Remarque : l'appel de cette fonction entraîne un comportement indéfini si isValid() renvoie false pour ce QFuture. Si QFuture n'est pas encore lancé, appelez waitForFinished() avant d'appeler cette fonction pour éviter un comportement indéfini.
Voir aussi result(), results(), takeResult() et resultCount().
int QFuture::resultCount() const
Renvoie le nombre de résultats continus disponibles dans ce futur. Le nombre réel de résultats stockés peut être différent de cette valeur, en raison de lacunes dans l'ensemble des résultats. Il est toujours prudent de parcourir les résultats de 0 à resultCount().
Voir également result(), resultAt(), results() et takeResult().
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QList<T> QFuture::results() const
Renvoie tous les résultats du futur. Si les résultats ne sont pas immédiatement disponibles, cette fonction se bloque et attend qu'ils soient disponibles. Notez que results() renvoie une copie des résultats stockés en interne. L'obtention de tous les résultats d'un type de mouvement uniquement T n'est pas prise en charge pour le moment. Cependant, vous pouvez toujours itérer à travers la liste des résultats de type "move-only" en utilisant des itérateurs de type STL ou des itérateurs de type Java en lecture seule.
Remarque : l'appel à cette fonction entraîne un comportement indéfini si isValid() renvoie false pour ce QFuture. Si QFuture n'est pas encore lancé, appelez waitForFinished() avant d'appeler cette fonction pour éviter un comportement indéfini.
Voir aussi result(), resultAt(), takeResult(), resultCount() et isValid().
void QFuture::resume()
Reprend le calcul asynchrone représenté par future(). Il s'agit d'une méthode de commodité qui appelle simplement setSuspended(false).
Voir aussi suspend().
[since 6.0] void QFuture::setSuspended(bool suspend)
Si suspend est vrai, cette fonction suspend le calcul asynchrone représenté par le future(). Si le calcul est déjà suspendu, cette fonction ne fait rien. QFutureWatcher ne cesse pas immédiatement de fournir des signaux de progression et de résultat prêt lorsque le futur est suspendu. Au moment de la suspension, il se peut que des calculs soient encore en cours et ne puissent pas être arrêtés. Les signaux relatifs à ces calculs continueront d'être émis.
Si suspend est faux, cette fonction reprend le calcul asynchrone. Si le calcul n'a pas été suspendu auparavant, cette fonction ne fait rien.
Il faut savoir que tous les calculs ne peuvent pas être suspendus. Par exemple, le QFuture renvoyé par QtConcurrent::run() ne peut pas être suspendu ; mais le QFuture renvoyé par QtConcurrent::mappedReduced() peut l'être.
Cette fonction a été introduite dans Qt 6.0.
Voir aussi isSuspended(), suspend(), resume(), et toggleSuspended().
[since 6.0] void QFuture::suspend()
Suspend le calcul asynchrone représenté par ce futur. Il s'agit d'une méthode de commodité qui appelle simplement setSuspended(true).
Cette fonction a été introduite dans Qt 6.0.
Voir aussi resume().
[since 6.0] template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::takeResult()
Cette fonction n'est appelée que si isValid() renvoie true, sinon le comportement est indéfini. Cette fonction prend (déplace) le premier résultat de l'objet QFuture, lorsqu'un seul résultat est attendu. S'il y a d'autres résultats, ils sont rejetés après avoir pris le premier. Si le résultat n'est pas immédiatement disponible, cette fonction se bloque et attend que le résultat devienne disponible. Le site QFuture essaiera d'utiliser la sémantique de déplacement si possible, et reviendra à la construction de copie si le type n'est pas déplaçable. Une fois le résultat obtenu, isValid() sera évalué comme false.
Note : QFuture permet en général de partager les résultats entre différents objets QFuture (et potentiellement entre différents threads). takeResult() a été introduit pour permettre à QFuture de fonctionner avec des types uniquement déplaçables (comme std::unique_ptr), et suppose donc qu'un seul thread peut déplacer les résultats hors du futur, et qu'il ne le fait qu'une seule fois. Notez également que la prise en compte de la liste de tous les résultats n'est pas supportée pour le moment. Cependant, vous pouvez toujours itérer à travers la liste des résultats de déplacement uniquement en utilisant des itérateurs de style STL ou des itérateurs de style Java en lecture seule.
Cette fonction a été introduite dans Qt 6.0.
Voir aussi result(), results(), resultAt(), et isValid().
[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(Function &&function)
Attache une continuation à ce futur, permettant d'enchaîner plusieurs calculs asynchrones si désiré, en utilisant la politique Sync. function est un appelable qui prend un argument du type emballé par ce futur si celui-ci a un résultat (n'est pas un QFuture<void>). Sinon, il ne prend aucun argument. Cette méthode renvoie un nouveau QFuture qui empaquette une valeur du type renvoyé par function. Le futur retourné sera dans un état non initialisé jusqu'à ce que la continuation attachée soit invoquée, ou jusqu'à ce que ce futur échoue ou soit annulé.
Remarque : utilisez d'autres surcharges de cette méthode si vous avez besoin de lancer la continuation dans un thread séparé.
Vous pouvez enchaîner plusieurs opérations de cette manière :
QFuture<int> future = ...; future.then([](int res1){ ... }).then([](int res2){ ... })...
Ou :
QFuture<void> future = ...; future.then([](){ ... }).then([](){ ... })...
La continuation peut également prendre un argument QFuture (au lieu de sa valeur), représentant le futur précédent. Cela peut être utile si, par exemple, QFuture a plusieurs résultats et que l'utilisateur souhaite y accéder dans la suite. Ou bien l'utilisateur a besoin de gérer l'exception du futur précédent à l'intérieur de la continuation, pour ne pas interrompre la chaîne de continuations multiples. Par exemple :
QFuture<int> future = someIntFuture; future.then([](QFuture<int> f) { try { //... auto result = f.result(); //... } catch (QException &e) { // handle the exception } }).then([](){/*...*/});
Avertissement : Si le futur précédent contient plusieurs résultats de type T, et que la suite prend un argument de type T comme paramètre, seul le premier résultat du futur précédent QFuture sera traité dans la suite !
Si le futur précédent lève une exception et que celle-ci n'est pas traitée dans la continuation, l'exception sera propagée au futur de continuation, afin de permettre à l'appelant de la traiter :
QFuture<int> future = someIntFuture; auto continuation = future.then([](int res1){ /*...*/ return res1; }).then([](int res2){ /*...*/ return res2; })/*...*/; //... // future throws an exception try { auto result = continuation.result(); } catch (QException &e) { // handle the exception }
Dans ce cas, toute la chaîne de continuations sera interrompue.
Remarque : si ce futur est annulé, les continuations qui lui sont attachées seront également annulées.
Il s'agit d'une fonction surchargée.
Cette fonction a été introduite dans Qt 6.0.
Voir aussi onFailed() et onCanceled().
[since 6.1] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QObject *context, Function &&function)
Attache une continuation à ce futur, ce qui permet d'enchaîner plusieurs calculs asynchrones si on le souhaite. Lorsque le calcul asynchrone représenté par ce futur se termine, function sera invoqué dans le fil d'exécution de l'objet context. Cela peut être utile si la suite doit être invoquée dans un thread spécifique. Cela peut être utile si la suite doit être invoquée dans un thread spécifique, par exemple :
// somewhere in the main thread auto future = QtConcurrent::run([] { // This will run in a separate thread //... }).then(this, [] { // Update UI elements });
La suite attachée à QtConcurrent::run met à jour les éléments de l'interface utilisateur et ne peut pas être invoquée à partir d'un fil d'exécution autre que l'interface utilisateur. Ainsi, this est fourni comme contexte à .then(), afin de s'assurer qu'il sera invoqué dans le fil d'exécution principal.
Les suites suivantes seront également invoquées à partir du même contexte, à moins qu'un contexte différent ou une politique de lancement ne soient spécifiés :
auto future = QtConcurrent::run([] { //... }).then(this, [] { // Update UI elements }).then([] { // This will also run in the main thread });
Ceci est dû au fait que, par défaut, .then() est invoqué dans le même fil d'exécution que le précédent.
Mais notez que si la suite est attachée alors que ce futur est déjà terminé, elle sera invoquée immédiatement, dans le thread qui exécute then():
QObject *context /*...*/; auto future = cachedResultsReady ? QtFuture::makeReadyVoidFuture() : QtConcurrent::run([] { /* compute result */}); auto continuation = future.then(context, [] { // Runs in the context's thread }).then([] { // May or may not run in the context's thread });
Dans l'exemple ci-dessus, si cachedResultsReady est true et qu'un futur prêt est renvoyé, il est possible que le premier .then() se termine avant que le second ne soit attaché. Dans ce cas, le problème sera résolu dans le fil d'exécution actuel. Par conséquent, en cas de doute, transmettez le contexte explicitement.
Si le context est détruit avant la fin de la chaîne, le futur est annulé. Cela implique qu'un gestionnaire d'annulation peut être invoqué lorsque le context n'est plus valide. Pour se prémunir contre cela, capturez le context en tant que QPointer:
QObject *context /*...*/; QFuture<Result> future /*...*/; auto continuation = future.then(context, [context](Result result) { // ... }).onCanceled([context = QPointer(context)] { if (!context) return; // context was destroyed already // handle cancellation });
Lorsque l'objet contextuel est détruit, l'annulation se produit immédiatement. Les futures précédents dans la chaîne ne sont pas annulés et continuent à fonctionner jusqu'à ce qu'ils soient terminés.
Remarque : lors de l'appel de cette méthode, il convient de s'assurer que le site context reste en vie pendant la mise en place de la chaîne.
Il s'agit d'une fonction surchargée.
Cette fonction a été introduite dans Qt 6.1.
Voir aussi onFailed() et onCanceled().
[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QThreadPool *pool, Function &&function)
Attache une continuation à ce futur, ce qui permet d'enchaîner plusieurs calculs asynchrones si on le souhaite. Lorsque le calcul asynchrone représenté par ce futur se termine, function sera planifié sur pool.
Il s'agit d'une fonction surchargée.
Cette fonction a été introduite dans Qt 6.0.
Voir aussi onFailed() et onCanceled().
[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QtFuture::Launch policy, Function &&function)
Attache une continuation à ce futur, ce qui permet d'enchaîner plusieurs calculs asynchrones. Lorsque le calcul asynchrone représenté par ce futur se termine, function sera invoqué selon le lancement donné policy. Un nouveau QFuture représentant le résultat de la continuation est renvoyé.
En fonction de policy, la suite sera invoquée dans le même thread que ce future, dans un nouveau thread, ou héritera de la politique de lancement et du pool de threads de ce future. Si aucune politique de lancement n'est spécifiée (voir la surcharge ne prenant qu'un callable), la politique Sync sera utilisée.
Dans l'exemple suivant, les deux continuations seront invoquées dans un nouveau thread (mais dans le même).
QFuture<int> future = ...; future.then(QtFuture::Launch::Async, [](int res){ ... }).then([](int res2){ ... });
Dans l'exemple suivant, les deux continuations seront invoquées dans de nouveaux threads utilisant le même pool de threads.
QFuture<int> future = ...; future.then(QtFuture::Launch::Async, [](int res){ ... }) .then(QtFuture::Launch::Inherit, [](int res2){ ... });
Voir la documentation de l'autre surcharge pour plus de détails sur function.
Il s'agit d'une fonction surchargée.
Cette fonction a été introduite dans Qt 6.0.
Voir aussi onFailed() et onCanceled().
[since 6.0] void QFuture::toggleSuspended()
Bascule l'état de suspension du calcul asynchrone. En d'autres termes, si le calcul est en cours de suspension ou suspendu, l'appel à cette fonction le reprend ; si le calcul est en cours d'exécution, il est suspendu. Il s'agit d'une méthode de commodité pour appeler setSuspended( !(isSuspending() || isSuspended())).
Cette fonction a été introduite dans Qt 6.0.
Voir aussi setSuspended(), suspend(), et resume().
[since 6.4] template <typename U> QFuture<U> QFuture::unwrap()
Déballe le futur interne de ce QFuture<T>, où T est un futur de type QFuture<U>, c'est-à-dire que ce futur a le type QFuture<QFuture<U>>. Par exemple :
unwrappedFuture sera réalisé dès que le futur interne imbriqué dans outerFuture sera réalisé, avec le même résultat ou la même exception et dans le même fil de discussion qui signale que le futur interne est terminé. Si le futur interne est annulé, unwrappedFuture sera également annulé.
Ceci est particulièrement utile lorsque l'on enchaîne plusieurs calculs et que l'un d'entre eux renvoie un QFuture comme type de résultat. Par exemple, disons que nous voulons télécharger plusieurs images à partir d'une URL, les mettre à l'échelle et les réduire en une seule image en utilisant QtConcurrent::mappedReduced(). Nous pourrions écrire quelque chose comme :
auto downloadImages = [] (const QUrl &url) { QList<QImage> images; //... return images; }; auto processImages = [scale, reduceImages](const QList<QImage> &images) { return QtConcurrent::mappedReduced(images, scale, reduceImages); }; auto show = [](const QImage &image) { /*...*/ }; auto future = QtConcurrent::run(downloadImages, url) .then(processImages) .unwrap() .then(show);
Ici, QtConcurrent::mappedReduced() renvoie un QFuture<QImage>, donc .then(processImages) renvoie un QFuture<QFuture<QImage>>. Puisque show() prend un QImage comme argument, le résultat de .then(processImages) ne peut pas lui être transmis directement. Nous devons appeler .unwrap(), qui récupérera le résultat du futur interne lorsqu'il sera prêt et le transmettra à la suite suivante.
En cas d'imbrication multiple, .unwrap() descend au niveau le plus bas :
Cette fonction a été introduite dans Qt 6.4.
void QFuture::waitForFinished()
Attend que le calcul asynchrone se termine (y compris les calculs cancel()ed), c'est-à-dire jusqu'à ce que isFinished() renvoie true.
QFuture<T> &QFuture::operator=(const QFuture<T> &other)
Attribue other à ce futur et renvoie une référence à ce futur.
© 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.