QFuture Class
template <typename T> class QFutureLa classe QFuture représente le résultat d'un calcul asynchrone. En savoir plus...
| 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
- Membres obsolètes
- QFuture fait partie des classes de gestion des threads.
Remarque : toutes les fonctions de cette classe sont sûres pour les threads, à l'exception des 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 est une classe de modèle dont le paramètre de modèle T spécifie le type de résultats produits par le calcul asynchrone.
QFuture permet de synchroniser des threads sur un ou plusieurs résultats qui seront disponibles ultérieurement. Le résultat peut être de n'importe quel type disposant de constructeurs par défaut, de copie et éventuellement de 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 soit 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 plusieurs résultats, la fonction resultCount() renvoie le nombre de résultats consécutifs. Cela signifie qu’il est toujours sûr de parcourir les résultats de 0 à resultCount(). La fonction takeResult() invalide un future, et toute tentative ultérieure d’accéder au ou aux résultats de ce future entraîne un comportement indéfini. La fonction 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 constitue une autre manière d'accéder aux résultats du « future ».
Si le résultat d’un calcul asynchrone doit être transmis à un autre, QFuture offre un moyen pratique d’enchaîner plusieurs calculs séquentiels à l’aide de then(). onCanceled() peut être utilisé pour ajouter un gestionnaire à appeler si le QFuture est annulé. De plus, onFailed() peut être utilisé pour gérer les éventuelles erreurs survenues 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 tout de même indiquer l'état d'erreur de QFuture en intégrant le type d'erreur au type QFuture. Par exemple, vous pouvez utiliser std::variant, std::any ou un type similaire pour stocker le résultat ou l'échec, ou bien créer votre propre type personnalisé.
L'exemple ci-dessous montre comment la gestion des erreurs peut être effectuée sans utiliser d'exceptions. Supposons que nous souhaitions envoyer une requête réseau pour récupérer un fichier volumineux à partir d’un emplacement réseau. Nous souhaitons ensuite l’écrire sur le système de fichiers et renvoyer son emplacement en cas de réussite. Ces deux opérations peuvent échouer en raison d’erreurs différentes. Nous utilisons donc ` std::variant ` pour stocker 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 à l’aide de ` 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. Par exemple :
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é, avec une exception ou avec un résultat), la fonction suivante ` onCanceled()`, ` onFailed()` ou ` then()` sera appelée. Ainsi, si ` testFuture ` est exécutée avec succès, ` Block 1 ` sera appelée. Si celle-ci réussit également, la fonction suivante ` then()` (ou `Block 4`) sera appelée. Si testFuture est annulée ou échoue en raison d’une exception, ce sont respectivement Block 2 ou Block 3 qui seront appelées. La méthode suivante, then(), sera ensuite appelée, et le processus se répète.
Remarque : si Block 2 est invoquée et lève une exception, la méthode suivante onFailed() (Block 3) la gérera. Si l’ordre de onFailed() et onCanceled() était inversé, l’exception se propagerait aux continuations suivantes et serait finalement interceptée 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é à la continuation suivante then(), qui sera également annulée. Dans ce cas, Block 6 sera donc appelé.
Le « future » ne peut avoir qu’une seule continuation. 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 en réalité le même objet QFuture, car ils partagent le même état interne. Par conséquent, l’appel de then sur f2 écrasera la continuation spécifiée pour f1. Ainsi, seul "second" sera affiché lors de l’exécution de ce code.
QFuture propose également des moyens d’interagir avec un calcul en cours d’exécution. Par exemple, le calcul peut être annulé à l’aide de la fonction ` cancel()`. Pour suspendre ou reprendre le calcul, utilisez la fonction ` setSuspended()` ou l’une des fonctions de commodité ` suspend()`, ` resume()` ou ` toggleSuspended()`. Notez que tous les calculs asynchrones en cours d'exécution ne peuvent pas être annulés ou suspendus. Par exemple, le « future » renvoyé par QtConcurrent::run() ne peut pas être annulé ; en revanche, celui renvoyé par QtConcurrent::mappedReduced() le peut.
Les informations de progression sont fournies par les fonctions ` progressValue()`, ` progressMinimum()`, ` progressMaximum()` et ` progressText()`. La fonction ` waitForFinished()` bloque le thread appelant et l'oblige à attendre la fin du calcul, garantissant ainsi que tous les résultats sont disponibles.
L'état du calcul représenté par un QFuture peut être interrogé à l'aide des fonctions isCanceled(), isStarted(), isFinished(), isRunning(), isSuspending() ou isSuspended().
QFuture<void> est spécialisé de manière à ne contenir aucune des fonctions de récupération de résultats. Tout objet QFuture<T> peut également être assigné ou copié dans un QFuture<void>. Cela s’avère utile lorsque seules les informations d’état ou de progression sont nécessaires, et non les données de résultat proprement dites.
Pour interagir avec les 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 seront résolus lorsqu’un signal est émis. Cela permet de travailler avec les signaux comme avec des objets `QFuture`. Par exemple, si vous combinez cela avec ` then()`, vous pouvez associer plusieurs continuations à un signal, qui seront 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 futurs et suivre le moment où le dernier ou le premier d’entre eux s’achève.
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 implémente un algorithme de « work-stealing » 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 du QFuture.
Remarque : pour lancer un calcul et stocker les résultats dans un QFuture, utilisez QPromise ou l’une des API du Qt Concurrent framework.
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()
Crée un « future » vide et annulé.
QFuture::QFuture(const QFuture<T> &other)
Crée une copie de other.
Voir également operator=().
QFuture::~QFuture()
Détruit l'avenir.
Notez que cette méthode 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 « future » 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 type STL pointant vers le premier résultat dans le futur.
Voir également constBegin() et end().
void QFuture::cancel()
Annule le calcul asynchrone représenté par ce « future ». Notez que l'annulation est asynchrone. Utilisez ` waitForFinished()` après avoir appelé `cancel()` lorsque vous avez besoin d'une annulation synchrone.
Les résultats actuellement disponibles restent accessibles sur un « future » annulé, mais aucun nouveau résultat ne sera disponible après l’appel de cette fonction. Tout objet ` QFutureWatcher ` surveillant ce « future » n’émettra pas de signaux de progression ni de résultat prêt sur un « future » annulé.
Sachez que tous les calculs asynchrones en cours d'exécution ne peuvent pas être annulés. Par exemple, le « future » renvoyé par QtConcurrent::run() ne peut pas être annulé ; en revanche, celui renvoyé par QtConcurrent::mappedReduced() peut l'être.
Voir également cancelChain().
[since 6.10] void QFuture::cancelChain()
Annule l'intégralité 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 continuation ` Then 2 `, les gestionnaires d’annulation ` OnCanceled 1 ` et ` OnCanceled 2 ` seront tous deux 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 « future » 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 continuations, comme le montre l’exemple ci-dessus.
Si l’une des continuations de la chaîne exécute un calcul asynchrone et renvoie un objet QFuture la représentant, l’appel à cancelChain() ne sera pas propagé vers ce calcul imbriqué une fois celui-ci lancé. En effet, le « future » ne sera disponible dans la chaîne de continuation que lorsque le « future » externe sera résolu, mais l’annulation peut survenir alors que le « future » externe et le « future » imbriqué attendent tous deux la fin de leurs calculs. Dans ce cas, le « future » 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 d’exécution, il ne peut être annulé qu’en appelant nested.cancel().
Cette fonction a été introduite dans Qt 6.10.
Voir également cancel().
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::constBegin() const
Renvoie un itérateur de type STL constant pointant vers le premier résultat dans le futur.
Voir également begin() et constEnd().
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::constEnd() const
Renvoie un itérateur de type STL (const) pointant vers le résultat imaginaire situé après le dernier résultat dans le futur.
Voir également constBegin() et end().
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::end() const
Renvoie un itérateur de type STL (const) pointant vers le résultat imaginaire situé après le dernier résultat dans le futur.
Voir également begin() et constEnd().
bool QFuture::isCanceled() const
Renvoie ` true ` si le calcul asynchrone a été annulé à l'aide de la fonction ` cancel()` ; sinon, renvoie ` false`.
Notez que le calcul peut encore être en cours 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 « future » 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 à l'adresse 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 ce QFuture n'est pas encore lancé, appelez waitForFinished() avant d'appeler cette fonction pour éviter tout comportement indéfini.
Voir également resultAt(), resultCount() et takeResult().
bool QFuture::isRunning() const
Renvoie « true » si le calcul asynchrone représenté par ce « future » est en cours d'exécution ; sinon, renvoie « false ».
bool QFuture::isStarted() const
Renvoie « true » si le calcul asynchrone représenté par ce « future » 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 en vigueur, ce qui signifie qu’aucun résultat ni aucune mise à jour de l’état d’avancement n’est attendu.
Cette fonction a été introduite dans Qt 6.0.
Voir également setSuspended(), toggleSuspended() et isSuspending().
[since 6.0] bool QFuture::isSuspending() const
Renvoie true si le calcul asynchrone a été suspendu à l'aide de la fonction suspend(), mais que le traitement n'est pas encore suspendu et que le calcul est toujours en cours. Renvoie false dans le cas contraire.
Pour vérifier si la suspension est effectivement active, utilisez plutôt isSuspended().
Cette fonction a été introduite dans Qt 6.0.
Voir également setSuspended(), toggleSuspended() et isSuspended().
[since 6.0] bool QFuture::isValid() const
Renvoie « true » si un ou plusieurs résultats sont accessibles ou peuvent être récupérés à partir de cet objet ` QFuture `. Renvoie « false » si l'objet ` QPromise ` associé n'a pas encore démarré ou si le résultat a déjà été récupéré à partir du `future`.
Remarque : la valeur de retour de cette fonction indique uniquement si le résultat du « future » peut être consommé, et non s’il est prêt. Cette fonction renverra « true » lorsque l’ QPromise associé est lancé, 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 également 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)
Associe une handler d’annulation à ce « future ». Le « future » renvoyé se comporte exactement comme ce « future » (il a le même état et le même résultat), sauf si ce « future » est annulé. L’ handler est une fonction qui ne prend aucun argument et renvoie une valeur du type encapsulé par ce « future ». Après l’annulation, le « future » renvoyé encapsule la valeur renvoyée par handler.
S’il est associé avant l’annulation, ` handler ` sera appelé dans le même thread que celui qui signale la fin du « future » après l’annulation. Si le gestionnaire est associé après que ce « future » a déjà été annulé, il sera appelé immédiatement dans le thread qui exécute ` onCanceled()`. Par conséquent, le gestionnaire ne peut pas toujours faire d’hypothèses quant au thread sur lequel il sera exécuté. Utilisez la surcharge qui prend un objet de contexte si vous souhaitez contrôler le thread sur lequel le gestionnaire sera appelé.
L'exemple ci-dessous montre comment associer 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 l’ resultFuture aura pour résultat -1. Contrairement à testFuture, il ne se trouvera pas dans un état « Canceled ». Cela signifie que vous pouvez récupérer son résultat, y associer des continuations, etc.
Notez également que vous pouvez annuler la chaîne de continuations pendant leur exécution via le « future » qui a lancé la chaîne. Supposons que testFuture.cancel() ait été appelé alors que Block 1 était déjà en cours d’exécution. La continuation suivante détectera qu’une annulation a été demandée ; par conséquent, Block 2 sera ignoré et le gestionnaire d’annulation (Block 3) sera appelé.
Remarque : cette méthode renvoie un nouvel objet QFuture représentant le résultat de la chaîne de continuations. L'annulation de l'QFuture résultant n'entraînera pas en soi l'appel du gestionnaire d'annulation dans la chaîne qui y a conduit. Cela signifie que si vous appelez resultFuture.cancel(), Block 3 ne sera pas appelé : comme resultFuture est le future résultant de l'association du gestionnaire d'annulation à testFuture, aucun gestionnaire d'annulation n'a été associé à resultFuture lui-même. Seule l'annulation de testFuture ou des futures renvoyés par les continuations associées avant l'appel à onCancelled() peut déclencher Block 3.
Cette fonction a été introduite dans Qt 6.0.
Voir également 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)
Associe une handler d'annulation à ce « future », qui sera appelée lorsque le « future » sera annulé. L'handler est une fonction qui ne prend aucun argument. Elle sera appelée dans le thread de l'objet « context ». Cela peut s'avérer utile si l'annulation doit être gérée dans un thread spécifique.
Si l’ context est détruit avant la fin de la chaîne, le future est annulé. Voir then() pour plus de détails.
Remarque : lors de l’appel de cette méthode, il faut s’assurer que l’ context reste actif pendant la mise en place de la chaîne.
Consultez 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 également then() et onFailed().
[since 6.0] template <typename Function, typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>> QFuture<T> QFuture::onFailed(Function &&handler)
Associe un gestionnaire d’erreurs à ce « future », afin de gérer les éventuelles exceptions. Le « future » renvoyé se comporte exactement comme ce « future » (il a le même état et le même résultat), sauf si ce « future » échoue en raison d’une exception.
L’ handler est une fonction qui ne prend aucun argument ou un seul argument, permettant de filtrer selon des types d’erreurs spécifiques, à l’instar de l’instruction catch. Elle renvoie une valeur du type encapsulé par ce « future ». Après l’échec, le « future » renvoyé encapsule la valeur renvoyée par handler.
Le gestionnaire ne sera invoqué que si une exception est levée. Si l'exception est levée après l’attachement de ce gestionnaire, celui-ci est exécuté dans le thread qui signale que le « future » est terminé à la suite de l’exception. Si le gestionnaire est associé alors que ce « future » a déjà échoué, il sera appelé immédiatement, dans le thread qui exécute ` onFailed()`. Par conséquent, le gestionnaire ne peut pas toujours faire d’hypothèses quant au thread sur lequel il sera exécuté. Utilisez la surcharge qui prend un objet de contexte si vous souhaitez contrôler le thread sur lequel le gestionnaire est appelé.
L’exemple ci-dessous montre comment associer 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 -1Si plusieurs gestionnaires sont attachés, le premier gestionnaire correspondant au type d’exception levée sera appelé. Par exemple :
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 levée, l'exception sera propagée au `Future` 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
}Remarque : vous pouvez toujours associer un gestionnaire ne prenant aucun argument pour gérer tous les types d’exceptions et éviter d’écrire un bloc try-catch.
Cette fonction a été introduite dans Qt 6.0.
Voir également 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)
Associe un gestionnaire d'erreurs à ce « future », afin de gérer toute exception que le « future » pourrait lever ou qu'il a déjà levée. Renvoie un objet « QFuture » du même type que ce « future ». Le gestionnaire ne sera appelé qu’en cas d’exception, dans le thread de l’objet context. Cela peut s’avérer utile si l’échec doit être géré 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 associé à ` QtConcurrent::run ` met à jour les éléments de l'interface utilisateur et ne peut pas être appelé depuis un thread non-GUI. ` this ` est donc fourni comme contexte à ` .onFailed()`, afin de garantir qu'il sera appelé dans le thread 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 faut s’assurer que l’ context reste active pendant la configuration de la chaîne.
Consultez 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 également ` then()` et ` onCanceled()`.
int QFuture::progressMaximum() const
Renvoie la valeur maximale de ` progressValue()`.
Voir également progressValue() et progressMinimum().
int QFuture::progressMinimum() const
Renvoie la valeur minimale de ` progressValue()`.
Voir également progressValue() et progressMaximum().
QString QFuture::progressText() const
Renvoie la représentation textuelle (facultative) de la progression telle qu'elle est signalée par le calcul asynchrone.
Notez que tous les calculs ne fournissent pas une représentation textuelle de la progression ; par conséquent, cette fonction peut renvoyer une chaîne vide.
int QFuture::progressValue() const
Renvoie la valeur de progression actuelle, comprise entre progressMinimum() et progressMaximum().
Voir également progressMinimum() et progressMaximum().
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::result() const
Renvoie le premier résultat disponible. Si le résultat n'est pas immédiatement disponible, cette fonction se bloque et attend qu'il le devienne. Il s'agit d'une méthode pratique permettant d'appeler resultAt(0). Notez que result() renvoie une copie du résultat stocké en interne. Si T est un type « move-only », ou si vous ne souhaitez pas copier le résultat, utilisez plutôt takeResult().
Remarque : l’appel de cette fonction entraîne un comportement indéfini si isValid() renvoie false pour ce QFuture. Si ce QFuture n’a pas encore été lancé, appelez waitForFinished() avant d’appeler cette fonction pour éviter tout comportement indéfini.
Voir également resultAt(), results() et takeResult().
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::resultAt(int index) const
Renvoie le résultat de index à un moment ultérieur. 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 ce QFuture n'est pas encore lancé, appelez waitForFinished() avant d'appeler cette fonction afin d'éviter tout comportement indéfini.
Voir également 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 différer de cette valeur, en raison d'intervalles vides dans l'ensemble des résultats. Il est toujours sûr 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 « future ». Si les résultats ne sont pas immédiatement disponibles, cette fonction se bloque et attend qu’ils le deviennent. Notez que la méthode ` results() ` renvoie une copie des résultats stockés en interne. L'obtention de tous les résultats d'un type « move-only » T n'est pas prise en charge pour le moment. Vous pouvez toutefois parcourir la liste des résultats « move-only » à l'aide d'itérateurs de type STL ou d'itérateurs de type Java en lecture seule.
Remarque : l’appel de cette fonction entraîne un comportement indéfini si isValid() renvoie false pour cette QFuture. Si cette QFuture n’a pas encore été lancée, appelez waitForFinished() avant d’appeler cette fonction pour éviter tout comportement indéfini.
Voir également result(), resultAt(), takeResult(), resultCount() et isValid().
void QFuture::resume()
Reprend le calcul asynchrone représenté par future(). Il s'agit d'une méthode pratique qui se contente d'appeler setSuspended(false).
Voir également suspend().
[since 6.0] void QFuture::setSuspended(bool suspend)
Si la valeur de ` suspend ` est vraie, cette fonction suspend le calcul asynchrone représenté par `future()`. Si le calcul est déjà suspendu, cette fonction ne fait rien. ` QFutureWatcher ` ne cessera pas immédiatement d'émettre les signaux de progression et de résultat lorsque le `future` est suspendu. Au moment de la suspension, il se peut que certains 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’était pas suspendu auparavant, cette fonction ne fait rien.
Notez que tous les calculs ne peuvent pas être suspendus. Par exemple, l’ QFuture renvoyée par QtConcurrent::run() ne peut pas être suspendue ; en revanche, l’ QFuture renvoyée par QtConcurrent::mappedReduced() peut l’être.
Cette fonction a été introduite dans Qt 6.0.
Voir également isSuspended(), suspend(), resume() et toggleSuspended().
[since 6.0] void QFuture::suspend()
Suspend le calcul asynchrone représenté par ce « future ». Il s'agit d'une méthode pratique qui se contente d'appeler ` setSuspended(true)`.
Cette fonction a été introduite dans Qt 6.0.
Voir également ` resume()`.
[since 6.0] template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::takeResult()
N'appelez cette fonction que si ` isValid()` renvoie ` true` ; sinon, le comportement est indéfini. Cette fonction récupère (déplace) le premier résultat de l'objet ` QFuture `, lorsqu'un seul résultat est attendu. S'il existe d'autres résultats, ils sont ignorés après la récupération du premier. Si le résultat n’est pas immédiatement disponible, cette fonction se bloque et attend qu’il le devienne. La fonction ` QFuture ` tentera d’utiliser la sémantique de déplacement si possible, et recourra à la construction par copie si le type n’est pas déplaçable. Une fois le résultat extrait, ` isValid()` s’évaluera comme ` false`.
Remarque : ` QFuture ` permet en général de partager les résultats entre différents objets ` QFuture ` (et potentiellement entre différents threads). La méthode `takeResult()` a été introduite pour permettre à ` QFuture ` de fonctionner également avec des types « move-only » (tels que `std::unique_ptr`) ; elle part donc du principe qu’un seul thread peut extraire les résultats du `future`, et ce, une seule fois. Notez également que la récupération de la liste de tous les résultats n’est pas prise en charge pour le moment. Vous pouvez toutefois parcourir la liste des résultats de type « move-only » à l’aide d’itérateurs de type STL ou d’itérateurs de type Java en lecture seule.
Cette fonction a été introduite dans Qt 6.0.
Voir également result(), results(), resultAt() et isValid().
[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(Function &&function)
Ajoute une continuation à ce « future », ce qui permet d’enchaîner plusieurs calculs asynchrones si nécessaire, en utilisant la politique « Sync ». ` function ` est une fonction qui prend un argument du type encapsulé par ce « future » si celui-ci a un résultat (s’il n’est pas de type ` QFuture<void>`). Sinon, elle ne prend aucun argument. Cette méthode renvoie un nouvel objet ` QFuture ` qui encapsule une valeur du type renvoyé par ` function`. Le `future` renvoyé restera dans un état non initialisé jusqu’à ce que la continuation associée soit invoquée, ou jusqu’à ce que ce `future` échoue ou soit annulé.
Remarque : utilisez d'autres surcharges de cette méthode si vous devez lancer la continuation dans un thread distinct.
Vous pouvez enchaîner plusieurs opérations comme suit :
QFuture<int> future = ...;
future.then([](int res1){ ... }).then([](int res2){ ... })...Ou :
QFuture<void> future = ...;
future.then([](){ ... }).then([](){ ... })...La continuation peut également prendre un argument de type ` QFuture ` (au lieu de sa valeur), représentant le `future` précédent. Cela peut s’avérer utile si, par exemple, ` QFuture ` renvoie plusieurs résultats et que l’utilisateur souhaite y accéder au sein de la continuation. Ou si l’utilisateur doit gérer l’exception du `future` précédent au sein de la continuation, afin de 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 « future » précédent contient plusieurs résultats de type ` T`, et que la continuation prend un argument de type ` T ` en paramètre, seul le premier résultat du « QFuture » précédent sera traité dans la continuation !
Si le « future » précédent lève une exception et que celle-ci n’est pas gérée au sein de la continuation, l’exception sera propagée au « future » de continuation, afin de permettre à l’appelant de la gérer :
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 « future » est annulé, les continuations qui y sont associées seront également annulées.
Il s'agit d'une fonction surchargée.
Cette fonction a été introduite dans Qt 6.0.
Voir également ` onFailed()` et ` onCanceled()`.
[since 6.1] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QObject *context, Function &&function)
Ajoute une continuation à ce « future », ce qui permet d'enchaîner plusieurs calculs asynchrones si nécessaire. Lorsque le calcul asynchrone représenté par ce « future » s'achève, la méthode ` function ` sera appelée dans le thread de l'objet ` context `. Cela peut s'avérer utile si la continuation doit être appelé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 continuation associée à QtConcurrent::run met à jour les éléments de l'interface utilisateur et ne peut pas être appelée depuis un thread non-GUI. Ainsi, this est fourni comme contexte à .then(), afin de garantir qu'elle sera appelée dans le thread principal.
Les continuations suivantes seront également invoquées à partir du même contexte, à moins qu’un contexte ou une politique de lancement différent(e) ne soit spécifié(e) :
auto future = QtConcurrent::run([] {
//...
}).then(this, [] {
// Update UI elements
}).then([] {
// This will also run in the main thread
});En effet, par défaut, ` .then() ` est appelé depuis le même thread que le précédent.
Mais notez que si la continuation est attachée après que ce « future » se soit déjà terminé, elle sera appelé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, il sera résolu dans le thread actuel. Par conséquent, en cas de doute, transmettez explicitement le contexte.
Si l’ context est détruit avant la fin de la chaîne, le « future » est annulé. Cela implique qu’un gestionnaire d’annulation pourrait être appelé alors que l’ context n’est plus valide. Pour éviter cela, capturez l’ context sous la forme d’un « 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 context est détruit, l’annulation se produit immédiatement. Les futures précédentes de la chaîne ne sont pas annulées et continuent de s’exécuter jusqu’à ce qu’elles soient terminées.
Remarque : lors de l’appel de cette méthode, il faut s’assurer que l’ context reste actif pendant la configuration de la chaîne.
Il s'agit d'une fonction surchargée.
Cette fonction a été introduite dans Qt 6.1.
Voir également ` onFailed()` et ` onCanceled()`.
[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QThreadPool *pool, Function &&function)
Ajoute une continuation à ce « future », ce qui permet d'enchaîner plusieurs calculs asynchrones si nécessaire. Lorsque le calcul asynchrone représenté par ce « future » sera terminé, la fonction function sera planifiée sur pool.
Il s’agit d’une fonction surchargée.
Cette fonction a été introduite dans Qt 6.0.
Voir également onFailed() et onCanceled().
[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QtFuture::Launch policy, Function &&function)
Associe une continuation à ce « future », ce qui permet d'enchaîner plusieurs calculs asynchrones. Lorsque le calcul asynchrone représenté par ce « future » s'achève, la méthode ` function ` sera appelée conformément à l'policy` de lancement spécifiée. Un nouveau « QFuture » représentant le résultat de la continuation est renvoyé.
En fonction de la policy, la continuation sera appelé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){ ... });Consultez 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 également ` onFailed()` et ` onCanceled()`.
[since 6.0] void QFuture::toggleSuspended()
Active ou désactive l'état de suspension du calcul asynchrone. En d'autres termes, si le calcul est en cours de suspension ou déjà suspendu, l'appel de cette fonction le reprend ; si le calcul est en cours d'exécution, il est suspendu. Il s'agit d'une méthode pratique permettant d'appeler setSuspended(!(isSuspending() || isSuspended())).
Cette fonction a été introduite dans Qt 6.0.
Voir également setSuspended(), suspend() et resume().
[since 6.4] template <typename U> QFuture<U> QFuture::unwrap()
Déballe le « future » interne de cet « QFuture<T> », où T est un « future » de type QFuture<U>, c'est-à-dire que ce « future » est de type QFuture<QFuture<U>>. Par exemple :
unwrappedFuture sera résolu dès que le « future » interne imbriqué dans l’ outerFuture sera résolu, avec le même résultat ou la même exception, et dans le même thread que celui qui signale la fin du « future » interne. Si le « future » interne est annulé, unwrappedFuture sera également annulé.
Ceci est particulièrement utile lors de l’enchaînement de plusieurs calculs, dont l’un renvoie un ` QFuture ` comme type de résultat. Par exemple, supposons que nous souhaitions télécharger plusieurs images à partir d’une URL, les redimensionner, puis les réduire en une seule image à l’aide de `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>>`. Comme ` show() ` prend un ` QImage ` en 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 `future` interne lorsqu’il sera prêt et le transmettra à la continuation suivante.
En cas d’imbrication multiple, ` .unwrap() ` descend jusqu’au niveau le plus profond :
Cette fonction a été introduite dans Qt 6.4.
void QFuture::waitForFinished()
Attend que le calcul asynchrone soit terminé (y compris les calculs effectués via ` cancel()`), c'est-à-dire jusqu'à ce que ` isFinished()` renvoie ` true`.
QFuture<T> &QFuture::operator=(const QFuture<T> &other)
Attribue la valeur « other » à ce « future » et renvoie une référence à ce « future ».
© 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.