QFuture Class

template <typename T> class QFuture

Die Klasse QFuture repräsentiert das Ergebnis einer asynchronen Berechnung. Mehr...

Kopfzeile: #include <QFuture>
CMake: find_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmake: QT += core

Hinweis: Alle Funktionen dieser Klasse sind bis auf die folgenden Ausnahmen thread-sicher:

Öffentliche Typen

Öffentliche Funktionen

QFuture()
QFuture(const QFuture<T> &other)
~QFuture()
QFuture<T>::const_iterator begin() const
void cancel()
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)

Detaillierte Beschreibung

QFuture ermöglicht die Synchronisation von Threads mit einem oder mehreren Ergebnissen, die zu einem späteren Zeitpunkt bereitstehen. Das Ergebnis kann von jedem Typ sein, der Default-, Copy- und möglicherweise Move-Konstruktoren hat. Wenn ein Ergebnis zum Zeitpunkt des Aufrufs der Funktionen result(), resultAt(), results() und takeResult() nicht verfügbar ist, wartet QFuture, bis das Ergebnis verfügbar wird. Sie können die Funktion isResultReadyAt() verwenden, um festzustellen, ob ein Ergebnis verfügbar ist oder nicht. Für QFuture-Objekte, die mehr als ein Ergebnis liefern, gibt die Funktion resultCount() die Anzahl der fortlaufenden Ergebnisse zurück. Das bedeutet, dass es immer sicher ist, durch die Ergebnisse von 0 bis resultCount() zu iterieren. takeResult() macht einen future ungültig, und jeder nachfolgende Versuch, auf das Ergebnis oder die Ergebnisse des future zuzugreifen, führt zu undefiniertem Verhalten. isValid() sagt Ihnen, ob auf Ergebnisse zugegriffen werden kann.

QFuture bietet einen Iterator im Java-Stil (QFutureIterator) und einen Iterator im STL-Stil (QFuture::const_iterator). Die Verwendung dieser Iteratoren ist eine weitere Möglichkeit, auf Ergebnisse in der Zukunft zuzugreifen.

Wenn das Ergebnis einer asynchronen Berechnung an eine andere übergeben werden muss, bietet QFuture eine bequeme Möglichkeit, mehrere sequenzielle Berechnungen mit then() zu verketten. onCanceled() kann verwendet werden, um einen Handler hinzuzufügen, der aufgerufen wird, wenn QFuture abgebrochen wird. Darüber hinaus kann onFailed() verwendet werden, um alle Fehler zu behandeln, die in der Kette aufgetreten sind. Beachten Sie, dass QFuture auf Exceptions für die Fehlerbehandlung angewiesen ist. Wenn die Verwendung von Exceptions keine Option ist, können Sie trotzdem den Fehlerzustand von QFuture angeben, indem Sie den Fehlertyp zum Bestandteil des QFuture-Typs machen. Sie können z.B. std::variant, std::any oder ähnliches verwenden, um das Ergebnis oder den Fehler zu speichern oder einen eigenen Typ erstellen.

Das folgende Beispiel demonstriert, wie die Fehlerbehandlung ohne Verwendung von Exceptions erfolgen kann. Nehmen wir an, wir wollen eine Netzwerkanforderung senden, um eine große Datei von einem Netzwerkstandort zu erhalten. Dann wollen wir sie in das Dateisystem schreiben und im Erfolgsfall ihren Speicherort zurückgeben. Beide Vorgänge können mit unterschiedlichen Fehlern fehlschlagen. Daher verwenden wir std::variant, um das Ergebnis oder den Fehler zu speichern:

using NetworkReply = std::variant<QByteArray, QNetworkReply::NetworkError>;

enum class IOError { FailedToRead, FailedToWrite };
using IOResult = std::variant<QString, IOError>;

Und wir kombinieren die beiden Operationen mit 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

Es ist möglich, mehrere Fortsetzungen und Handler in beliebiger Reihenfolge zu verketten. Zum Beispiel:

QFuture<int> testFuture = ...;
auto resultFuture = testFuture.then([](int res) {
    // Block 1
}).onCanceled([] {
    // Block 2
}).onFailed([] {
    // Block 3
}).then([] {
    // Block 4
}).onFailed([] {
    // Block 5
}).onCanceled([] {
    // Block 6
});

Je nach Zustand von testFuture (abgebrochen, hat eine Ausnahme oder hat ein Ergebnis), wird die nächste onCanceled(), onFailed() oder then() aufgerufen. Wenn also testFuture erfolgreich ausgeführt wird, wird Block 1 aufgerufen. Wenn es ebenfalls erfolgreich ist, wird die nächste then() (Block 4) aufgerufen. Wenn testFuture abgebrochen wird oder mit einer Ausnahme fehlschlägt, wird entweder Block 2 oder Block 3 aufgerufen. Danach wird der nächste then() aufgerufen, und die Geschichte wiederholt sich.

Hinweis: Wenn Block 2 aufgerufen wird und eine Ausnahme auslöst, wird die folgende onFailed() (Block 3) diese behandeln. Wäre die Reihenfolge von onFailed() und onCanceled() umgekehrt, würde sich der Ausnahmezustand auf die nächsten Fortsetzungen ausbreiten und schließlich in Block 5 abgefangen werden.

Im nächsten Beispiel wird die erste onCanceled() (Block 2) entfernt:

QFuture<int> testFuture = ...;
auto resultFuture = testFuture.then([](int res) {
    // Block 1
}).onFailed([] {
    // Block 3
}).then([] {
    // Block 4
}).onFailed([] {
    // Block 5
}).onCanceled([] {
    // Block 6
});

Wenn testFuture abgebrochen wird, wird sein Zustand an die nächste then() weitergegeben, die dann ebenfalls abgebrochen wird. In diesem Fall wird also Block 6 aufgerufen.

Die Zukunft kann nur eine Fortsetzung haben. Betrachten Sie das folgende Beispiel:

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

In diesem Fall sind f1 und f2 effektiv das gleiche QFuture-Objekt, da sie den gleichen internen Zustand haben. Folglich wird der Aufruf von then auf f2 die für f1 angegebene Fortsetzung überschreiben. Daher wird nur "second" gedruckt, wenn dieser Code ausgeführt wird.

QFuture bietet auch Möglichkeiten zur Interaktion mit einer laufenden Berechnung. Zum Beispiel kann die Berechnung mit der Funktion cancel() abgebrochen werden. Um die Berechnung anzuhalten oder fortzusetzen, verwenden Sie die Funktion setSuspended() oder eine der Komfortfunktionen suspend(), resume() oder toggleSuspended(). Beachten Sie, dass nicht alle laufenden asynchronen Berechnungen abgebrochen oder unterbrochen werden können. Zum Beispiel kann der von QtConcurrent::run() zurückgegebene Future nicht abgebrochen werden, aber der von QtConcurrent::mappedReduced() zurückgegebene Future schon.

Fortschrittsinformationen werden von den Funktionen progressValue(), progressMinimum(), progressMaximum() und progressText() bereitgestellt. Die Funktion waitForFinished() veranlasst den aufrufenden Thread zu blockieren und auf den Abschluss der Berechnung zu warten, um sicherzustellen, dass alle Ergebnisse verfügbar sind.

Der Zustand der durch eine QFuture repräsentierten Berechnung kann mit den Funktionen isCanceled(), isStarted(), isFinished(), isRunning(), isSuspending() oder isSuspended() abgefragt werden.

QFuture<void> ist darauf spezialisiert, keine der Funktionen zum Abrufen von Ergebnissen zu enthalten. Jedes QFuture<T> kann auch in ein QFuture<void> zugewiesen oder kopiert werden. Dies ist nützlich, wenn nur Status- oder Fortschrittsinformationen benötigt werden - nicht die eigentlichen Ergebnisdaten.

Um mit laufenden Tasks über Signale und Slots zu interagieren, verwenden Sie QFutureWatcher.

Sie können auch QtFuture::connect() verwenden, um Signale mit einem QFuture-Objekt zu verbinden, das aufgelöst wird, wenn ein Signal ausgesendet wird. Dies ermöglicht die Arbeit mit Signalen wie mit QFuture-Objekten. In Kombination mit then() können Sie zum Beispiel mehrere Fortsetzungen an ein Signal anhängen, die im gleichen oder einem neuen Thread aufgerufen werden.

Die Funktionen QtFuture::whenAll() und QtFuture::whenAny() können verwendet werden, um mehrere Futures zu kombinieren und zu verfolgen, wann der letzte oder erste von ihnen abgeschlossen ist.

Ein fertiges QFuture-Objekt mit einem Wert oder ein QFuture-Objekt mit einer Ausnahme kann mit den Komfortfunktionen QtFuture::makeReadyVoidFuture(), QtFuture::makeReadyValueFuture(), QtFuture::makeReadyRangeFuture() und QtFuture::makeExceptionalFuture() erstellt werden.

Hinweis: Einige APIs (siehe QFuture::then() oder verschiedene QtConcurrent Methodenüberladungen) erlauben es, die Berechnung in einem bestimmten Threadpool zu planen. QFuture implementiert jedoch einen Work-Stealing-Algorithmus, um Deadlocks zu verhindern und die Thread-Nutzung zu optimieren. Als Ergebnis können Berechnungen direkt in dem Thread ausgeführt werden, der das Ergebnis von QFuture anfordert.

Hinweis: Um eine Berechnung zu starten und die Ergebnisse in einem QFuture zu speichern, verwenden Sie QPromise oder eine der APIs im Qt Concurrent Framework.

Siehe auch QPromise, QtFuture::connect(), QtFuture::makeReadyVoidFuture(), QtFuture::makeReadyValueFuture(), QtFuture::makeReadyRangeFuture(), QtFuture::makeExceptionalFuture(), QFutureWatcher, und Qt Concurrent.

Dokumentation der Mitgliedstypen

QFuture::ConstIterator

Qt-style Synonym für QFuture::const_iterator.

Dokumentation der Mitgliedsfunktionen

QFuture::QFuture()

Konstruiert eine leere, abgebrochene Zukunft.

QFuture::QFuture(const QFuture<T> &other)

Konstruiert eine Kopie von other.

Siehe auch operator=().

QFuture::~QFuture()

Zerstört den Future.

Beachten Sie, dass dadurch die asynchrone Berechnung weder abgewartet noch abgebrochen wird. Verwenden Sie waitForFinished() oder QFutureSynchronizer, wenn Sie sicherstellen müssen, dass die Berechnung abgeschlossen ist, bevor der Future zerstört wird.

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::begin() const

Gibt einen const STL-artigen Iterator zurück, der auf das erste Ergebnis in der Zukunft zeigt.

Siehe auch constBegin() und end().

void QFuture::cancel()

Bricht die durch diesen Future dargestellte asynchrone Berechnung ab. Beachten Sie, dass der Abbruch asynchron erfolgt. Verwenden Sie waitForFinished() nach dem Aufruf von cancel(), wenn Sie einen synchronen Abbruch benötigen.

Auf aktuell verfügbare Ergebnisse kann weiterhin über einen abgebrochenen Future zugegriffen werden, aber neue Ergebnisse werden nach dem Aufruf dieser Funktion nicht mehr verfügbar. Jedes QFutureWatcher Objekt, das diesen Future beobachtet, wird bei einem abgebrochenen Future keine Fortschritts- und Ergebnisbereitschaftssignale liefern.

Beachten Sie, dass nicht alle laufenden asynchronen Berechnungen abgebrochen werden können. Zum Beispiel kann der von QtConcurrent::run() zurückgegebene Future nicht abgebrochen werden, aber der von QtConcurrent::mappedReduced() zurückgegebene Future schon.

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::constBegin() const

Gibt einen const STL-artigen Iterator zurück, der auf das erste Ergebnis in der Zukunft zeigt.

Siehe auch begin() und constEnd().

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::constEnd() const

Gibt einen const STL-artigen Iterator zurück, der auf das imaginäre Ergebnis nach dem letzten Ergebnis in der Zukunft zeigt.

Siehe auch constBegin() und end().

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::end() const

Gibt einen const STL-artigen Iterator zurück, der auf das imaginäre Ergebnis nach dem letzten Ergebnis in der Zukunft zeigt.

Siehe auch begin() und constEnd().

bool QFuture::isCanceled() const

Gibt true zurück, wenn die asynchrone Berechnung mit der Funktion cancel() abgebrochen wurde; andernfalls wird false zurückgegeben.

Beachten Sie, dass die Berechnung noch laufen kann, obwohl diese Funktion true zurückgibt. Siehe cancel() für weitere Details.

bool QFuture::isFinished() const

Gibt true zurück, wenn die asynchrone Berechnung, die durch diesen future repräsentiert wird, beendet ist; andernfalls wird false zurückgegeben.

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> bool QFuture::isResultReadyAt(int index) const

Gibt true zurück, wenn das Ergebnis unter index sofort verfügbar ist; andernfalls wird false zurückgegeben.

Hinweis: Der Aufruf von isResultReadyAt() führt zu undefiniertem Verhalten, wenn isValid() false für dieses QFuture zurückgibt.

Siehe auch resultAt(), resultCount(), und takeResult().

bool QFuture::isRunning() const

Gibt true zurück, wenn die asynchrone Berechnung, die durch diesen future repräsentiert wird, gerade läuft; andernfalls wird false zurückgegeben.

bool QFuture::isStarted() const

Gibt true zurück, wenn die asynchrone Berechnung, die durch diesen future repräsentiert wird, gestartet wurde; andernfalls wird false zurückgegeben.

[since 6.0] bool QFuture::isSuspended() const

Gibt true zurück, wenn eine Unterbrechung der asynchronen Berechnung angefordert wurde und diese in Kraft ist, was bedeutet, dass keine weiteren Ergebnisse oder Fortschrittsänderungen erwartet werden.

Diese Funktion wurde in Qt 6.0 eingeführt.

Siehe auch setSuspended(), toggleSuspended(), und isSuspending().

[since 6.0] bool QFuture::isSuspending() const

Gibt true zurück, wenn die asynchrone Berechnung mit der Funktion suspend() unterbrochen wurde, die Arbeit aber noch nicht unterbrochen ist und die Berechnung noch läuft. Andernfalls wird false zurückgegeben.

Um zu prüfen, ob die Unterbrechung tatsächlich in Kraft ist, verwenden Sie stattdessen isSuspended().

Diese Funktion wurde in Qt 6.0 eingeführt.

Siehe auch setSuspended(), toggleSuspended(), und isSuspended().

[since 6.0] bool QFuture::isValid() const

Gibt true zurück, wenn ein Ergebnis oder Ergebnisse von diesem QFuture Objekt abgerufen oder entnommen werden können. Gibt false zurück, wenn das Ergebnis aus dem future entnommen wurde.

Diese Funktion wurde in Qt 6.0 eingeführt.

Siehe auch takeResult(), result(), results(), und resultAt().

[since 6.0] template <typename Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>> QFuture<T> QFuture::onCanceled(Function &&handler)

Hängt eine Stornierung handler an diesen Future an. Der zurückgegebene Future verhält sich genau wie dieser Future (hat denselben Zustand und dasselbe Ergebnis), es sei denn, dieser Future wird abgebrochen. handler ist eine aufrufbare Variable, die keine Argumente annimmt und einen Wert des Typs zurückgibt, der von diesem Future verpackt wurde. Nach dem Abbruch verpackt der zurückgegebene Future den von handler zurückgegebenen Wert.

Wenn er vor dem Abbruch angehängt wird, wird handler in demselben Thread aufgerufen, der den Future nach dem Abbruch als beendet meldet. Wenn der Handler angehängt wird, nachdem dieser Future bereits abgebrochen wurde, wird er sofort in dem Thread aufgerufen, der onCanceled() ausführt. Daher kann der Handler nicht immer Annahmen darüber treffen, in welchem Thread er ausgeführt werden soll. Verwenden Sie die Überladung, die ein Kontextobjekt annimmt, wenn Sie steuern möchten, in welchem Thread der Handler aufgerufen wird.

Das folgende Beispiel zeigt, wie man einen Abbruch-Handler anfügt:

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

Wenn testFuture abgebrochen wird, wird Block 3 aufgerufen und resultFuture hat -1 als Ergebnis. Im Gegensatz zu testFuture befindet es sich nicht im Zustand Canceled. Das bedeutet, dass Sie sein Ergebnis abrufen, ihm Zählungen zuordnen können usw.

Beachten Sie auch, dass Sie die Kette der Fortsetzungen während ihrer Ausführung über den Future, der die Kette gestartet hat, abbrechen können. Angenommen, testFuture.cancel() wurde aufgerufen, während Block 1 bereits ausgeführt wird. Die nächste Fortsetzung wird erkennen, dass ein Abbruch angefordert wurde, so dass Block 2 übersprungen und der Abbruchhandler (Block 3) aufgerufen wird.

Hinweis: Diese Methode gibt ein neues QFuture zurück, das das Ergebnis der Fortsetzungskette darstellt. Das Abbrechen der resultierenden QFuture selbst ruft nicht den Abbruchhandler in der Kette auf, die zu ihr geführt hat. Das bedeutet, dass, wenn Sie resultFuture.cancel() aufrufen, Block 3 nicht aufgerufen wird: da resultFuture die Zukunft ist, die aus dem Anhängen des Abbruchhandlers an testFuture resultiert, wurden keine Abbruchhandler an resultFuture selbst angehängt. Nur die Stornierung von testFuture oder die Futures, die von den vor dem Aufruf von onCancelled() angehängten Continuations zurückgegeben werden, können Block 3 auslösen.

Diese Funktion wurde in Qt 6.0 eingeführt.

Siehe auch then() und 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)

Dies ist eine überladene Funktion.

Hängt an diesen Future eine Stornierung handler an, die aufgerufen wird, wenn der Future storniert wird. Die handler ist eine Callable, die keine Argumente entgegennimmt. Sie wird im Thread des context Objekts aufgerufen. Dies kann nützlich sein, wenn die Stornierung in einem bestimmten Thread behandelt werden muss.

Wenn context zerstört wird, bevor die Kette beendet ist, wird der Future abgebrochen. Siehe then() für Details.

Hinweis: Wenn diese Methode aufgerufen wird, sollte sichergestellt werden, dass context während des Aufbaus der Kette am Leben bleibt.

Siehe die Dokumentation der anderen Überladung für weitere Details über handler.

Diese Funktion wurde in Qt 6.1 eingeführt.

Siehe auch then() und onFailed().

[since 6.0] template <typename Function, typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>> QFuture<T> QFuture::onFailed(Function &&handler)

Hängt einen Fehlerbehandler an diesen Future an, um eventuelle Ausnahmen zu behandeln. Der zurückgegebene Future verhält sich genau wie dieser Future (hat denselben Zustand und dasselbe Ergebnis), es sei denn, dieser Future schlägt mit einer Ausnahme fehl.

handler ist eine Callable, die entweder kein Argument oder ein Argument entgegennimmt, um nach bestimmten Fehlertypen zu filtern, ähnlich wie die catch-Anweisung. Sie gibt einen Wert des Typs zurück, der von diesem Future verpackt wurde. Nach dem Fehler verpackt der zurückgegebene Future den von handler zurückgegebenen Wert.

Der Handler wird nur aufgerufen, wenn eine Ausnahme ausgelöst wird. Wenn die Ausnahme ausgelöst wird, nachdem dieser Handler angehängt wurde, wird der Handler in dem Thread ausgeführt, der den Future als Ergebnis der Ausnahme als beendet meldet. Wenn der Handler angehängt wird, nachdem dieser Future bereits fehlgeschlagen ist, wird er sofort in dem Thread aufgerufen, der onFailed() ausführt. Daher kann der Handler nicht immer Annahmen darüber treffen, in welchem Thread er ausgeführt werden soll. Verwenden Sie die Überladung, die ein Kontextobjekt annimmt, wenn Sie steuern möchten, in welchem Thread der Handler aufgerufen wird.

Das folgende Beispiel zeigt, wie ein Fehler-Handler angehängt werden kann:

QFuture<int> future = ...;
auto resultFuture = future.then([](int res) {
    ...
    throw Error();
    ...
}).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

Wenn mehrere Handler angehängt sind, wird der erste Handler, der mit dem Typ der ausgelösten Ausnahme übereinstimmt, aufgerufen. Ein Beispiel:

QFuture<int> future = ...;
future.then([](int res) {
    ...
    throw std::runtime_error("message");
    ...
}).onFailed([](const std::exception &e) {
    // This handler will be invoked
}).onFailed([](const std::runtime_error &e) {
    // This handler won't be invoked, because of the handler above.
});

Wenn keiner der Handler mit dem ausgelösten Ausnahmetyp übereinstimmt, wird die Ausnahme an den resultierenden Future weitergegeben:

QFuture<int> future = ...;
auto resultFuture = future.then([](int res) {
    ...
    throw Error("message");
    ...
}).onFailed([](const std::exception &e) {
    // Won't be invoked
}).onFailed([](const QException &e) {
    // Won't be invoked
});

try {
    auto result = resultFuture.result();
} catch(...) {
    // Handle the exception
}

Hinweis: Sie können jederzeit einen Handler ohne Argument anhängen, um alle Ausnahmetypen zu behandeln und das Schreiben des try-catch-Blocks zu vermeiden.

Diese Funktion wurde in Qt 6.0 eingeführt.

Siehe auch then() und onCanceled().

[since 6.1] template <typename Function, typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>> QFuture<T> QFuture::onFailed(QObject *context, Function &&handler)

Dies ist eine überladene Funktion.

Hängt einen Fehlerbehandler an diesen Future an, um alle Ausnahmen zu behandeln, die der Future auslöst oder die er bereits ausgelöst hat. Gibt eine QFuture vom gleichen Typ wie dieser Future zurück. Der Handler wird nur im Falle einer Ausnahme im Thread des context Objekts aufgerufen. Dies kann nützlich sein, wenn der Fehler in einem bestimmten Thread behandelt werden muss. Ein Beispiel:

// somewhere in the main thread
auto future = QtConcurrent::run([] {
    // This will run in a separate thread
    ...
    throw std::exception();
}).onFailed(this, [] {
   // Update UI elements
});

Der an QtConcurrent::run angehängte Fehler-Handler aktualisiert die UI-Elemente und kann nicht von einem Nicht-GUI-Thread aus aufgerufen werden. Daher wird this als Kontext für .onFailed() bereitgestellt, um sicherzustellen, dass er im Hauptthread aufgerufen wird.

Wenn context zerstört wird, bevor die Kette beendet ist, wird der Future abgebrochen. Siehe then() für Details.

Hinweis: Beim Aufruf dieser Methode sollte sichergestellt werden, dass die context während des Aufbaus der Kette am Leben bleibt.

Siehe die Dokumentation der anderen Überladung für weitere Details über handler.

Diese Funktion wurde in Qt 6.1 eingeführt.

Siehe auch then() und onCanceled().

int QFuture::progressMaximum() const

Gibt das Maximum zurück progressValue().

Siehe auch progressValue() und progressMinimum().

int QFuture::progressMinimum() const

Gibt das Minimum progressValue() zurück.

Siehe auch progressValue() und progressMaximum().

QString QFuture::progressText() const

Gibt die (optionale) textuelle Darstellung des Fortschritts zurück, wie er von der asynchronen Berechnung gemeldet wird.

Beachten Sie, dass nicht alle Berechnungen eine textuelle Darstellung des Fortschritts liefern, so dass diese Funktion eine leere Zeichenkette zurückgeben kann.

int QFuture::progressValue() const

Gibt den aktuellen Fortschrittswert zurück, der zwischen den Werten progressMinimum() und progressMaximum() liegt.

Siehe auch progressMinimum() und progressMaximum().

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::result() const

Gibt das erste Ergebnis in der Zukunft zurück. Wenn das Ergebnis nicht sofort verfügbar ist, blockiert diese Funktion und wartet, bis das Ergebnis verfügbar wird. Dies ist eine praktische Methode für den Aufruf von resultAt(0). Beachten Sie, dass result() eine Kopie des intern gespeicherten Ergebnisses zurückgibt. Wenn T ein reiner Verschiebetyp ist oder Sie das Ergebnis nicht kopieren wollen, verwenden Sie stattdessen takeResult().

Hinweis: Der Aufruf von result() führt zu undefiniertem Verhalten, wenn isValid() false für diesen QFuture zurückgibt.

Siehe auch resultAt(), results(), und takeResult().

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::resultAt(int index) const

Gibt das Ergebnis unter index in der Zukunft zurück. Wenn das Ergebnis nicht sofort verfügbar ist, blockiert diese Funktion und wartet, bis das Ergebnis verfügbar wird.

Hinweis: Der Aufruf von resultAt() führt zu undefiniertem Verhalten, wenn isValid() false für dieses QFuture zurückgibt.

Siehe auch result(), results(), takeResult(), und resultCount().

int QFuture::resultCount() const

Gibt die Anzahl der in diesem future verfügbaren kontinuierlichen Ergebnisse zurück. Die tatsächliche Anzahl der gespeicherten Ergebnisse kann aufgrund von Lücken in der Ergebnismenge von diesem Wert abweichen. Es ist immer sicher, durch die Ergebnisse von 0 bis resultCount() zu iterieren.

Siehe auch result(), resultAt(), results(), und takeResult().

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QList<T> QFuture::results() const

Gibt alle Ergebnisse aus der Zukunft zurück. Wenn die Ergebnisse nicht sofort verfügbar sind, blockiert diese Funktion und wartet, bis sie verfügbar werden. Beachten Sie, dass results() eine Kopie der intern gespeicherten Ergebnisse zurückgibt. Das Abrufen aller Ergebnisse eines "move-only"-Typs T wird zur Zeit nicht unterstützt. Sie können jedoch immer noch durch die Liste der Nur-Bewegung-Ergebnisse iterieren, indem Sie Iteratoren im STL-Stil oder schreibgeschützte Iteratoren im Java-Stil verwenden.

Hinweis: Der Aufruf von results() führt zu undefiniertem Verhalten, wenn isValid() false für dieses QFuture zurückgibt.

Siehe auch result(), resultAt(), takeResult(), resultCount(), und isValid().

void QFuture::resume()

Setzt die asynchrone Berechnung fort, die durch future() dargestellt wird. Dies ist eine Komfortmethode, die einfach setSuspended(false) aufruft.

Siehe auch suspend().

[since 6.0] void QFuture::setSuspended(bool suspend)

Wenn suspend wahr ist, unterbricht diese Funktion die asynchrone Berechnung, die durch future() dargestellt wird. Wenn die Berechnung bereits unterbrochen ist, tut diese Funktion nichts. QFutureWatcher wird nicht sofort aufhören, Fortschritts- und Ergebnisbereitschaftssignale zu liefern, wenn der future unterbrochen wird. Zum Zeitpunkt der Unterbrechung können noch Berechnungen im Gange sein, die nicht gestoppt werden können. Die Signale für solche Berechnungen werden weiterhin ausgegeben.

Wenn suspend falsch ist, setzt diese Funktion die asynchrone Berechnung fort. Wurde die Berechnung nicht vorher unterbrochen, bewirkt diese Funktion nichts.

Beachten Sie, dass nicht alle Berechnungen unterbrochen werden können. Zum Beispiel kann die QFuture, die von QtConcurrent::run() zurückgegeben wird, nicht unterbrochen werden, aber die QFuture, die von QtConcurrent::mappedReduced() zurückgegeben wird, kann dies.

Diese Funktion wurde in Qt 6.0 eingeführt.

Siehe auch isSuspended(), suspend(), resume(), und toggleSuspended().

[since 6.0] void QFuture::suspend()

Unterbricht die asynchrone Berechnung, die durch diesen Future dargestellt wird. Dies ist eine Komfortmethode, die einfach setSuspended(true) aufruft.

Diese Funktion wurde in Qt 6.0 eingeführt.

Siehe auch resume().

[since 6.0] template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::takeResult()

Rufen Sie diese Funktion nur auf, wenn isValid() true zurückgibt, ansonsten ist das Verhalten undefiniert. Diese Funktion nimmt (verschiebt) das erste Ergebnis aus dem QFuture Objekt, wenn nur ein Ergebnis erwartet wird. Falls weitere Ergebnisse vorhanden sind, werden sie nach der Entnahme des ersten verworfen. Wenn das Ergebnis nicht sofort verfügbar ist, blockiert diese Funktion und wartet, bis das Ergebnis verfügbar wird. QFuture versucht, wenn möglich, die Move-Semantik zu verwenden, und greift auf die Copy-Konstruktion zurück, wenn der Typ nicht beweglich ist. Nachdem das Ergebnis übernommen wurde, wird isValid() als false ausgewertet.

Hinweis: QFuture erlaubt es im Allgemeinen, die Ergebnisse zwischen verschiedenen QFuture Objekten (und potentiell zwischen verschiedenen Threads) zu teilen. takeResult() wurde eingeführt, damit QFuture auch mit move-only-Typen (wie std::unique_ptr) arbeiten kann, so dass es davon ausgeht, dass nur ein Thread die Ergebnisse aus der Zukunft verschieben kann, und dies auch nur einmal tut. Beachten Sie auch, dass die Liste aller Ergebnisse im Moment nicht unterstützt wird. Sie können jedoch immer noch durch die Liste der Nur-Verschiebe-Ergebnisse iterieren, indem Sie Iteratoren im STL-Stil oder Nur-Lese-Iteratoren im Java-Stil verwenden.

Diese Funktion wurde in Qt 6.0 eingeführt.

Siehe auch result(), results(), resultAt(), und isValid().

[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(Function &&function)

Dies ist eine überladene Funktion.

Hängt eine Fortsetzung an diese Future an, die es erlaubt, mehrere asynchrone Berechnungen zu verketten, falls gewünscht, unter Verwendung der Sync Richtlinie. function ist eine aufrufbare Funktion, die ein Argument des Typs annimmt, der von dieser Future verpackt wurde, wenn diese ein Ergebnis hat (ist kein QFuture<void>). Andernfalls nimmt es keine Argumente an. Diese Methode gibt eine neue QFuture zurück, die einen Wert des Typs verpackt, der von function zurückgegeben wird. Die zurückgegebene Zukunft befindet sich in einem nicht initialisierten Zustand, bis die angehängte Fortsetzung aufgerufen wird, oder bis diese Zukunft fehlschlägt oder abgebrochen wird.

Hinweis: Verwenden Sie andere Überladungen dieser Methode, wenn Sie die Fortsetzung in einem separaten Thread starten müssen.

Sie können mehrere Operationen auf diese Weise verketten:

QFuture<int> future = ...;
future.then([](int res1){ ... }).then([](int res2){ ... })...

Oder:

QFuture<void> future = ...;
future.then([](){ ... }).then([](){ ... })...

Die Fortsetzung kann auch ein QFuture Argument (anstelle seines Wertes) annehmen, das die vorherige Zukunft darstellt. Dies kann nützlich sein, wenn z. B. QFuture mehrere Ergebnisse hat und der Benutzer innerhalb der Fortsetzung auf diese zugreifen möchte. Oder der Benutzer muss die Ausnahme des vorherigen Futures innerhalb der Fortsetzung behandeln, um die Kette von mehreren Fortsetzungen nicht zu unterbrechen. Zum Beispiel:

QFuture<int> future = ...;
    future.then([](QFuture<int> f) {
        try {
            ...
            auto result = f.result();
            ...
        } catch (QException &e) {
            // handle the exception
        }
    }).then(...);

Wenn der vorherige Future eine Exception auslöst und diese nicht innerhalb der Continuation behandelt wird, wird die Exception an den Continuation-Future weitergegeben, damit der Aufrufer sie behandeln kann:

QFuture<int> future = ...;
auto continuation = future.then([](int res1){ ... }).then([](int res2){ ... })...
...
// future throws an exception
try {
    auto result = continuation.result();
} catch (QException &e) {
    // handle the exception
}

In diesem Fall wird die gesamte Kette der Fortsetzungen unterbrochen.

Hinweis: Wenn dieser Future abgebrochen wird, werden die mit ihm verbundenen Continuations ebenfalls abgebrochen.

Diese Funktion wurde in Qt 6.0 eingeführt.

Siehe auch onFailed() und onCanceled().

[since 6.1] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QObject *context, Function &&function)

Dies ist eine überladene Funktion.

Hängt eine Fortsetzung an diesen Future an und ermöglicht so die Verkettung mehrerer asynchroner Berechnungen, falls gewünscht. Wenn die asynchrone Berechnung, die durch diesen Future dargestellt wird, beendet ist, wird function im Thread des context Objekts aufgerufen. Dies kann nützlich sein, wenn die Fortsetzung in einem bestimmten Thread aufgerufen werden muss. Zum Beispiel:

// somewhere in the main thread
auto future = QtConcurrent::run([] {
    // This will run in a separate thread
    ...
}).then(this, [] {
   // Update UI elements
});

Die an QtConcurrent::run angehängte Fortsetzung aktualisiert die UI-Elemente und kann nicht von einem Nicht-GUI-Thread aus aufgerufen werden. Daher wird this als Kontext für .then() bereitgestellt, um sicherzustellen, dass sie im Hauptthread aufgerufen wird.

Die folgenden Fortsetzungen werden ebenfalls aus demselben Kontext aufgerufen, es sei denn, es wird ein anderer Kontext oder eine andere Startrichtlinie angegeben:

auto future = QtConcurrent::run([] {
    ...
}).then(this, [] {
   // Update UI elements
}).then([] {
    // This will also run in the main thread
});

Dies liegt daran, dass .then() standardmäßig aus demselben Thread wie der vorherige aufgerufen wird.

Beachten Sie jedoch, dass die Fortsetzung, wenn sie angehängt wird, nachdem dieser Future bereits beendet ist, sofort in dem Thread aufgerufen wird, der then() ausführt:

QObject *context = ...;
auto future = cachedResultsReady ? QtFuture::makeReadyValueFuture(result)
                                 : QtConcurrent::run([] { /* compute result */});
auto continuation = future.then(context, [] (Result result) {
    // Runs in the context's thread
}).then([] {
    // May or may not run in the context's thread
});

Wenn im obigen Beispiel cachedResultsReady zu true wird und eine fertige Zukunft zurückgegeben wird, ist es möglich, dass die erste .then() beendet wird, bevor die zweite angehängt wird. In diesem Fall wird sie im aktuellen Thread aufgelöst. Übergeben Sie daher im Zweifelsfall den Kontext explizit.

Wenn die context zerstört wird, bevor die Kette beendet ist, wird der Future abgebrochen. Dies bedeutet, dass ein Abbruch-Handler aufgerufen werden könnte, wenn die context nicht mehr gültig ist. Um dies zu verhindern, fangen Sie die context als QPointer ein:

QObject *context = ...;
auto future = ...;
auto continuation = future.then(context, [context](Result result) {
                               // ...
                           }).onCanceled([context = QPointer(context)] {
                               if (!context)
                                   return;  // context was destroyed already
                               // handle cancellation
                           });

Wenn das Kontextobjekt zerstört wird, erfolgt der Abbruch sofort. Frühere Futures in der Kette werden nicht abgebrochen und laufen weiter, bis sie beendet sind.

Hinweis: Beim Aufruf dieser Methode sollte sichergestellt werden, dass context während des Aufbaus der Kette aktiv bleibt.

Diese Funktion wurde in Qt 6.1 eingeführt.

Siehe auch onFailed() und onCanceled().

[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QThreadPool *pool, Function &&function)

Dies ist eine überladene Funktion.

Hängt eine Fortsetzung an diesen Future an und ermöglicht so die Verkettung mehrerer asynchroner Berechnungen, falls gewünscht. Wenn die asynchrone Berechnung, die durch diesen Future repräsentiert wird, beendet ist, wird function auf pool eingeplant.

Diese Funktion wurde in Qt 6.0 eingeführt.

Siehe auch onFailed() und onCanceled().

[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QtFuture::Launch policy, Function &&function)

Dies ist eine überladene Funktion.

Hängt eine Fortsetzung an diesen Future an und ermöglicht so die Verkettung mehrerer asynchroner Berechnungen. Wenn die asynchrone Berechnung, die durch diesen Future dargestellt wird, beendet ist, wird function entsprechend dem angegebenen Start policy aufgerufen. Es wird ein neues QFuture zurückgegeben, das das Ergebnis der Fortsetzung darstellt.

Je nach policy wird die Fortsetzung im selben Thread wie dieser Future oder in einem neuen Thread aufgerufen, oder sie erbt die Startrichtlinie und den Threadpool dieses Future. Wenn keine Startrichtlinie angegeben ist (siehe die Überladung, die nur einen Callable nimmt), wird die Richtlinie Sync verwendet.

Im folgenden Beispiel werden beide Fortsetzungen in einem neuen Thread (aber im selben) aufgerufen.

QFuture<int> future = ...;
future.then(QtFuture::Launch::Async, [](int res){ ... }).then([](int res2){ ... });

Im folgenden Beispiel werden beide Fortsetzungen in neuen Threads unter Verwendung desselben Threadpools aufgerufen.

QFuture<int> future = ...;
future.then(QtFuture::Launch::Async, [](int res){ ... })
      .then(QtFuture::Launch::Inherit, [](int res2){ ... });

Siehe die Dokumentation der anderen Überladung für weitere Details über function.

Diese Funktion wurde in Qt 6.0 eingeführt.

Siehe auch onFailed() und onCanceled().

[since 6.0] void QFuture::toggleSuspended()

Schaltet den angehaltenen Zustand der asynchronen Berechnung um. Mit anderen Worten: Wenn die Berechnung gerade unterbrochen oder ausgesetzt ist, wird sie durch den Aufruf dieser Funktion wieder aufgenommen; wenn die Berechnung läuft, wird sie ausgesetzt. Dies ist eine praktische Methode für den Aufruf von setSuspended(!(isSuspending() || isSuspended())).

Diese Funktion wurde in Qt 6.0 eingeführt.

Siehe auch setSuspended(), suspend(), und resume().

[since 6.4] template <typename U> QFuture<U> QFuture::unwrap()

Entpackt die innere Zukunft aus dieser QFuture<T>, wobei T eine Zukunft des Typs QFuture<U> ist, d.h. diese Zukunft hat den Typ QFuture<QFuture<U>>. Zum Beispiel:

QFuture<QFuture<int>> outerFuture = ...;
QFuture<int> unwrappedFuture = outerFuture.unwrap();

unwrappedFuture wird erfüllt, sobald die innere Zukunft, die in outerFuture verschachtelt ist, erfüllt ist, mit demselben Ergebnis oder derselben Ausnahme und in demselben Thread, der die innere Zukunft als beendet meldet. Wenn der innere Future abgebrochen wird, wird auch unwrappedFuture abgebrochen.

Dies ist besonders nützlich, wenn mehrere Berechnungen verkettet werden und eine davon ein QFuture als Ergebnistyp zurückgibt. Nehmen wir zum Beispiel an, wir wollen mehrere Bilder von einer URL herunterladen, die Bilder skalieren und sie mit QtConcurrent::mappedReduced() auf ein einziges Bild reduzieren. Wir könnten etwas schreiben wie:

auto downloadImages = [] (const QUrl &url) {
    QList<QImage> images;
    ...
    return images;
};

auto processImages = [](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);

Hier gibt QtConcurrent::mappedReduced() ein QFuture<QImage> zurück, so dass .then(processImages) ein QFuture<QFuture<QImage>> zurückgibt. Da show() ein QImage als Argument benötigt, kann das Ergebnis von .then(processImages) nicht direkt an diese Funktion übergeben werden. Wir müssen .unwrap() aufrufen, das das Ergebnis des inneren Futures erhält, wenn es fertig ist, und es an die nächste Fortsetzung weitergibt.

Im Falle einer mehrfachen Verschachtelung geht .unwrap() bis zur innersten Ebene hinunter:

QFuture<QFuture<QFuture<int>>>> outerFuture;
QFuture<int> unwrappedFuture = outerFuture.unwrap();

Diese Funktion wurde in Qt 6.4 eingeführt.

void QFuture::waitForFinished()

Wartet, bis die asynchrone Berechnung beendet ist (einschließlich der Berechnungen von cancel()ed), d. h. bis isFinished() true zurückgibt.

QFuture<T> &QFuture::operator=(const QFuture<T> &other)

Weist other diesem Future zu und gibt eine Referenz auf diesen Future zurück.

© 2025 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.