En esta página

Ejecución concurrente

La función QtConcurrent::run() ejecuta una función en un hilo separado. El valor de retorno de la función está disponible a través de la API QFuture.

QtConcurrent::run() es un método sobrecargado. Puede pensar en estas sobrecargas como modos ligeramente diferentes. En el modo básico, la función pasada a QtConcurrent::run() es capaz de informar simplemente de un único resultado de cálculo a quien la llama. En el modo de ejecución con promesa, la función pasada a QtConcurrent::run() puede hacer uso de la API adicional QPromise, que permite informar de múltiples resultados, informar del progreso, suspender el cálculo cuando lo solicite la persona que llama, o detener el cálculo a petición de la persona que llama.

Esta función forma parte del marco Qt Concurrent.

Optimizar incluye

Si incluye la cabecera <QtConcurrent>, se incluirá todo el módulo Qt Concurrent con todo el módulo Qt Core, lo que puede aumentar los tiempos de compilación y el tamaño de los binarios. Para utilizar la función QtConcurrent::run(), puede incluir una cabecera más específica:

#include <QtConcurrentRun>

Ejecución concurrente (modo básico)

La función pasada a QtConcurrent::run() puede informar del resultado a través de su valor de retorno.

Ejecutar una función en un hilo separado

Para ejecutar una función en otro hilo, utilice QtConcurrent::run():

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

Esto ejecutará aFunction en un hilo separado obtenido del predeterminado QThreadPool. Puede utilizar las clases QFuture y QFutureWatcher para monitorizar el estado de la función.

Para utilizar un grupo de hilos dedicado, puede pasar QThreadPool como primer argumento:

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

Pasar argumentos a la función

Pasar argumentos a la función se hace añadiéndolos a la llamada a QtConcurrent::run() inmediatamente después del nombre de la función. Por ejemplo:

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

Se hace una copia de cada argumento en el punto donde se llama a QtConcurrent::run(), y estos valores se pasan al hilo cuando comienza a ejecutar la función. Los cambios realizados en los argumentos después de llamar a QtConcurrent::run() no son visibles para el subproceso.

Tenga en cuenta que QtConcurrent::run no permite llamar directamente a funciones sobrecargadas. Por ejemplo, el código siguiente no compilará:

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

La solución más sencilla es llamar a la función sobrecargada a través de lambda:

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

O puede indicar al compilador qué sobrecarga elegir utilizando static_cast:

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

O qOverload:

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

Devolución de valores de la función

Cualquier valor de retorno de la función está disponible a través de QFuture:

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

Si no necesita el resultado (por ejemplo, porque la función devuelve void), utilizar la sobrecarga QThreadPool::start() tomando un objeto de función es más eficiente.

Como se ha documentado anteriormente, el paso de argumentos se realiza de la siguiente manera:

extern QString someFunction(const QByteArray &input);

QByteArray bytearray = ...;

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

Observe que la función QFuture::result() se bloquea y espera a que el resultado esté disponible. Utilice QFutureWatcher para obtener una notificación cuando la función haya finalizado su ejecución y el resultado esté disponible.

Características adicionales de la API

Uso de funciones miembro

QtConcurrent::run() también acepta punteros a funciones miembro. En Qt 6, el primer argumento debe ser el puntero a la función miembro, seguido de una referencia const o un puntero a una instancia de la clase. Pasar una referencia const es útil para llamar a funciones miembro const; pasar un puntero es útil para llamar a funciones miembro no const que modifican la instancia.

Por ejemplo, llamar a QByteArray::split() (una función miembro const) en un hilo separado se hace así:

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

La llamada a una función miembro no-const se hace así:

// 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

Uso de funciones lambda

La llamada a una función lambda se realiza del siguiente modo:

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

Llamar a una función modifica un objeto pasado por referencia se hace así:

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

Usar un objeto invocable se hace así:

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

Ejecución concurrente con promesa

El modo Run With Prom ise permite un mayor control de la tarea en ejecución comparado con el modo básico de QtConcurrent::run(). Permite informar del progreso de la tarea en ejecución, informar de múltiples resultados, suspender la ejecución si se ha solicitado, o cancelar la tarea a petición de quien la llama.

El argumento obligatorio QPromise

Se espera que la función pasada a QtConcurrent::run() en modo Run With Promise tenga un argumento adicional de tipo QPromise<T> &, donde T es el tipo del resultado del cálculo (debe coincidir con el tipo T de QFuture<T> devuelto por QtConcurrent::run()), como por ejemplo:

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

El argumento promise se instancia dentro de la función QtConcurrent::run(), y su referencia se pasa al aFunction invocado, por lo que el usuario no necesita instanciarlo, ni pasarlo explícitamente al llamar a QtConcurrent::run() en este modo.

El argumento adicional de tipo QPromise siempre tiene que aparecer como primer argumento en la lista de argumentos de la función, como:

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

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

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

Informe de resultados

A diferencia del modo básico de QtConcurrent::run(), se espera que la función pasada a QtConcurrent::run() en modo Run With Promise siempre devuelva el tipo void. La notificación de resultados se realiza mediante el argumento adicional de tipo QPromise. También permite la notificación múltiple de resultados, como:

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

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

Nota: No es necesario llamar a QPromise::start() y QPromise::finish() para indicar el comienzo y el final del cálculo (como se haría normalmente al utilizar QPromise). QtConcurrent::run() siempre los llamará antes de empezar y después de terminar la ejecución.

Suspender y cancelar la ejecución

La API QPromise también permite suspender y cancelar el cálculo, si se solicita:

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

La llamada a future.suspend() solicita a la tarea en ejecución que suspenda su ejecución. Tras llamar a este método, la tarea en ejecución se suspenderá tras la siguiente llamada a promise.suspendIfRequested() en su bucle de iteración. En este caso, la tarea en ejecución se bloqueará en una llamada a promise.suspendIfRequested(). La llamada bloqueada se desbloqueará tras la llamada a future.resume(). Nótese que internamente suspendIfRequested() utiliza la condición de espera para desbloquearse, por lo que el subproceso en ejecución pasa a un estado de reposo en lugar de malgastar sus recursos cuando se bloquea para comprobar periódicamente si la solicitud de reanudación proviene del subproceso que realiza la llamada.

La llamada a future.cancel() de la última línea provoca que la siguiente llamada a promise.isCanceled() devuelva true y aFunction devuelva inmediatamente sin ningún otro informe de resultados.

Nota: No es necesario llamar a QPromise::finish() para detener el cálculo después de la cancelación (como se haría normalmente al usar QPromise). QtConcurrent::run() siempre lo llamará después de terminar la ejecución.

Informes de progreso

También es posible informar del progreso de una tarea independientemente del informe de resultados, como:

void aFunción(QPromise<int> &promise) { promise.setProgressRange(0, 100); int result = 0; for(int i = 0; i < 100; ++i) { // calcula alguna parte de la tarea const int part = ...; result += part; promise.setProgressValue(i); } promise.addResult(result); }QFutureWatcher<int> watcher;QObject::connect(&vigilante, &QFutureWatcher::progressValueChanged, [](int progress){ ...; // actualizar GUI con un progreso    qDebug() << "current progress:" << progress;
}); watcher.setFuture(QtConcurrent::run(aFunction));

El llamador instala el QFutureWatcher para el QFuture devuelto por QtConcurrent::run() para conectarse a su señal progressValueChanged() y actualizar, por ejemplo, la interfaz gráfica de usuario en consecuencia.

Invocación de funciones con sobrecarga operator()()

Por defecto, QtConcurrent::run() no soporta functores con operator()() sobrecargado en modo Run With Promise. En el caso de funtores sobrecargados, el usuario necesita especificar explícitamente el tipo de resultado como un parámetro de plantilla pasado a QtConcurrent::run(), como:

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.