Auf dieser Seite

Paralleler Lauf

Die Funktion `QtConcurrent::run()` führt eine Funktion in einem separaten Thread aus. Der Rückgabewert der Funktion wird über die API „ QFuture “ bereitgestellt.

QtConcurrent::run() ist eine überladene Methode. Man kann sich diese Überladungen als leicht unterschiedliche Modi vorstellen. Im Basismodus kann die an QtConcurrent::run() übergebene Funktion lediglich ein einziges Berechnungsergebnis an ihren Aufrufer melden. Im Modus „Ausführung mit Promise“ kann die an `QtConcurrent::run()` übergebene Funktion die zusätzliche API ` QPromise ` nutzen, die die Meldung mehrerer Ergebnisse, Fortschrittsberichte, das Anhalten der Berechnung auf Anfrage des Aufrufers oder das Beenden der Berechnung auf Verlangen des Aufrufers ermöglicht.

Diese Funktion ist Teil des „ Qt Concurrent “-Frameworks.

Includes optimieren

Wenn Sie den Header „ <QtConcurrent> “ einbinden, werden das gesamte Modul „ Qt Concurrent “ sowie das gesamte Modul „ Qt Core “ eingebunden, was zu längeren Kompilierungszeiten und größeren Binärdateien führen kann. Um die Funktion „ QtConcurrent::run()“ zu verwenden, können Sie einen spezifischeren Header einbinden:

#include <QtConcurrentRun>

Paralleler Lauf (Basis-Modus)

Die an `QtConcurrent::run()` übergebene Funktion kann das Ergebnis über ihren Rückgabewert melden.

Ausführen einer Funktion in einem separaten Thread

Um eine Funktion in einem anderen Thread auszuführen, verwenden Sie QtConcurrent::run():

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

Dadurch wird ` aFunction ` in einem separaten Thread ausgeführt, der vom Standard- QThreadPool bereitgestellt wird. Mit den Klassen ` QFuture ` und ` QFutureWatcher ` können Sie den Status der Funktion überwachen.

Um einen dedizierten Thread-Pool zu verwenden, können Sie „ QThreadPool “ als erstes Argument übergeben:

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

Übergabe von Argumenten an die Funktion

Die Übergabe von Argumenten an die Funktion erfolgt, indem diese unmittelbar nach dem Funktionsnamen zum Aufruf von `QtConcurrent::run()` hinzugefügt werden. Zum Beispiel:

extern void aFunctionWithArguments(int arg1, double arg2, const QString &string);

int integer = ...;
double floatingPoint = ...;
QString string = ...;

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

An der Stelle, an der QtConcurrent::run() aufgerufen wird, wird von jedem Argument eine Kopie erstellt, und diese Werte werden an den Thread übergeben, sobald dieser mit der Ausführung der Funktion beginnt. Änderungen an den Argumenten, die nach dem Aufruf von QtConcurrent::run() vorgenommen werden, sind für den Thread nicht sichtbar.

Beachten Sie, dass „ QtConcurrent::run “ den direkten Aufruf überladener Funktionen nicht unterstützt. Der folgende Code lässt sich beispielsweise nicht kompilieren:

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

Die einfachste Abhilfe besteht darin, die überladene Funktion über ein Lambda-Ausdruck aufzurufen:

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

Oder Sie können dem Compiler mithilfe eines „ static_cast “ mitteilen, welche Überladung er wählen soll:

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

Oder „ qOverload “:

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

Rückgabewerte der Funktion

Jeder Rückgabewert der Funktion ist über ` QFuture` verfügbar:

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

Wenn Sie das Ergebnis nicht benötigen (zum Beispiel, weil die Funktion ` void` zurückgibt), ist die Verwendung der Überladung von ` QThreadPool::start()` mit einem Funktionsobjekt effizienter.

Wie oben beschrieben, erfolgt die Übergabe von Argumenten wie folgt:

extern QString someFunction(const QByteArray &input);

QByteArray bytearray = ...;

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

Beachten Sie, dass die Funktion ` QFuture::result()` blockiert und wartet, bis das Ergebnis verfügbar ist. Verwenden Sie ` QFutureWatcher `, um eine Benachrichtigung zu erhalten, sobald die Funktion die Ausführung beendet hat und das Ergebnis verfügbar ist.

Weitere API-Funktionen

Verwendung von Member-Funktionen

QtConcurrent::run() akzeptiert auch Zeiger auf Memberfunktionen. In Qt 6 muss das erste Argument der Zeiger auf die Memberfunktion sein, gefolgt von entweder einer const-Referenz oder einem Zeiger auf eine Instanz der Klasse. Die Übergabe einer const-Referenz ist nützlich beim Aufruf von const-Mitgliedsfunktionen; die Übergabe eines Zeigers ist nützlich für den Aufruf von Nicht-const-Mitgliedsfunktionen, die die Instanz verändern.

Beispielsweise erfolgt der Aufruf von ` QByteArray::split()` (einer `const`-Memberfunktion) in einem separaten Thread wie folgt:

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

Der Aufruf einer nicht-konstanten Memberfunktion erfolgt wie folgt:

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

Verwendung von Lambda-Funktionen

Der Aufruf einer Lambda-Funktion erfolgt wie folgt:

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

Das Aufrufen einer Funktion, die ein per Referenz übergebenes Objekt verändert, erfolgt wie folgt:

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

Die Verwendung eines aufrufbaren Objekts erfolgt wie folgt:

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

...

TestClass o;

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

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

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

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

Parallele Ausführung mit Promise

Der Modus „Run With Promise“ ermöglicht im Vergleich zum Basismodus von QtConcurrent::run() eine bessere Kontrolle über die ausgeführte Aufgabe. Er ermöglicht die Fortschrittsanzeige der ausgeführten Aufgabe, die Rückgabe mehrerer Ergebnisse, die Aussetzung der Ausführung auf Anfrage sowie das Abbrechen der Aufgabe auf Verlangen des Aufrufers.

Das obligatorische Argument „QPromise“

Die Funktion, die im Modus „Run With Promise“ an QtConcurrent::run() übergeben wird, muss ein zusätzliches Argument vom Typ „ QPromise<T> & “ enthalten, wobei „ T “ der Typ des Berechnungsergebnisses ist (er sollte mit dem Typ „ T “ von „ QFuture<T>“ übereinstimmen, der von QtConcurrent::run() zurückgegeben wird), wie z. B.:

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

Das Argument ` promise ` wird innerhalb der Funktion `QtConcurrent::run()` instanziiert, und seine Referenz wird an die aufgerufene Funktion ` aFunction` übergeben, sodass der Benutzer es weder instanziieren noch explizit übergeben muss, wenn er `QtConcurrent::run()` in diesem Modus aufruft.

Das zusätzliche Argument vom Typ ` QPromise ` muss immer als erstes Argument in der Argumentliste der Funktion stehen, wie hier:

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

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

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

Ergebnisse melden

Im Gegensatz zum Basis-Modus von `QtConcurrent::run()` wird erwartet, dass die an `QtConcurrent::run()` im „Run With Promise“-Modus übergebene Funktion stets den Typ `void` zurückgibt. Die Ergebnisausgabe erfolgt über das zusätzliche Argument vom Typ ` QPromise `. Dies ermöglicht auch die Ausgabe mehrerer Ergebnisse, wie zum Beispiel:

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

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

Hinweis: Es ist nicht erforderlich, QPromise::start() und QPromise::finish() aufzurufen, um den Beginn und das Ende der Berechnung zu kennzeichnen (wie es normalerweise bei der Verwendung von QPromise der Fall wäre). QtConcurrent::run() ruft diese Funktionen immer vor Beginn und nach Abschluss der Ausführung auf.

Ausführung unterbrechen und abbrechen

Die QPromise -API ermöglicht auf Wunsch auch das Anhalten und Abbrechen der Berechnung:

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

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

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

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

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

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

Der Aufruf von ` future.suspend() ` fordert die laufende Aufgabe auf, ihre Ausführung anzuhalten. Nach dem Aufruf dieser Methode wird die laufende Aufgabe nach dem nächsten Aufruf von ` promise.suspendIfRequested() ` in ihrer Iterationsschleife angehalten. In diesem Fall wird die laufende Aufgabe bei einem Aufruf von ` promise.suspendIfRequested()` blockiert. Der blockierte Aufruf wird freigegeben, nachdem ` future.resume() ` aufgerufen wurde. Beachten Sie, dass `suspendIfRequested()` intern eine Wartebedingung verwendet, um die Blockierung aufzuheben. Dadurch wechselt der laufende Thread in einen Leerlaufzustand, anstatt seine Ressourcen zu verschwenden, während er blockiert ist, um regelmäßig zu prüfen, ob die Fortsetzungsanforderung vom Thread des Aufrufers kam.

Der Aufruf von ` future.cancel() ` in der letzten Zeile bewirkt, dass der nächste Aufruf von ` promise.isCanceled() ` ` true ` zurückgibt und ` aFunction ` sofort ohne weitere Ergebnismeldung zurückkehrt.

Hinweis: Es ist nicht erforderlich, QPromise::finish() aufzurufen, um die Berechnung nach dem Abbruch zu beenden (wie es normalerweise bei der Verwendung von QPromise der Fall wäre). QtConcurrent::run() ruft diese Funktion immer nach Abschluss der Ausführung auf.

Fortschrittsmeldung

Es ist auch möglich, den Fortschritt einer Aufgabe unabhängig von der Ergebnisausgabe zu melden, zum Beispiel:

void aFunction(QPromise<int> &promise)
{
    promise.setProgressRange(0, 100);
    int result = 0;
    for (int i = 0; i < 100;++i) {
       // berechnet einen Teil der Aufgabe
        const int part =...;
        result+= part;
        promise.setProgressValue(i);
    }
    promise.addResult(result);
}

QFutureWatcher<int> watcher;
QObject::connect(&watcher, &QFutureWatcher::progressValueChanged, [](int progress){
    ...; // GUI mit dem Fortschritt aktualisieren
    qDebug() << "current progress:" << progress;
});
watcher.setFuture(QtConcurrent::run(aFunction));

Der Aufrufer registriert den ` QFutureWatcher ` für die von `QtConcurrent::run()` zurückgegebene ` QFuture `, um eine Verbindung zu deren Signal ` progressValueChanged() ` herzustellen und beispielsweise die grafische Benutzeroberfläche entsprechend zu aktualisieren.

Aufruf von Funktionen mit überladenem operator()()

Standardmäßig unterstützt QtConcurrent::run() im Modus „Run With Promise“ keine Funktoren mit überladenem operator()(). Bei überladenen Funktoren muss der Benutzer den Ergebnistyp explizit als Template-Parameter angeben, der an QtConcurrent::run() übergeben wird, wie folgt:

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

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

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