En esta página

Contador primario

Demuestra cómo monitorizar el progreso de operaciones concurrentes.

El siguiente ejemplo demuestra cómo crear una aplicación QtWidgets interactiva y no bloqueante utilizando la clase QFutureWatcher y las funciones filteredReduced de Qt Concurrent. Con este ejemplo, el usuario puede crear un QList de enteros que pueden ser redimensionados. La lista se rellenará automáticamente con números naturales empezando por 1 hasta n. A continuación, el programa buscará números primos dentro de la lista y mostrará el recuento total de números primos encontrados.

Ejecutar el ejemplo

Para ejecutar el ejemplo desde Qt Creatorabra el modo Welcome y seleccione el ejemplo de Examples. Para más información, consulte Qt Creator: Tutorial: Construir y ejecutar.

Configuración de las conexiones

La biblioteca Qt Concurrent proporciona las funciones filteredReduced, que pueden operar en dos modos: OrderedReduce and UnorderedReduce. En el modo OrderedReduce, se llama a la función reductora en el orden de la secuencia original, mientras que en el modo UnorderedReduce, se accede a los elementos de forma aleatoria.

Después de configurar la UI con los elementos deseados, es necesario conectarlos a las señales de las operaciones concurrentes utilizando el mecanismo Qt Signals & Slots. En este ejemplo, utilizamos la clase QFutureWatcher para monitorizar el progreso de las operaciones concurrentes y proporcionar las señales necesarias para implementar la GUI interactiva.

    ...
connect(ui->pushButton, &QPushButton::clicked,
        this, [this] { start(); });
connect(&watcher, &QFutureWatcher<Element>::finished,
        this, [this] { finish(); });
connect(&watcher, &QFutureWatcher<Element>::progressRangeChanged,
        ui->progressBar, &QProgressBar::setRange);
connect(&watcher, &QFutureWatcher<Element>::progressValueChanged,
        ui->progressBar, &QProgressBar::setValue);
    ...

La clase QFutureWatcher juega un papel vital en este ejemplo ya que proporciona las señales necesarias para actualizar la interfaz de usuario en respuesta a los cambios en las operaciones concurrentes.

Inicio de la operación simultánea

Después de conectar todas las señales y ranuras, y cuando el usuario presiona el QPushButton, la función start() es llamada.

En la función start(), llamamos a la función filteredReduced de Qt Concurrent y establecemos el futuro en el miembro QFutureWatcher. Para asegurar que esta operación se ejecuta realmente de forma concurrente, especificamos un QThreadPool separado como primer parámetro. Este enfoque también evita cualquier posible bloqueo en el pool de hilos global. Pasamos el QList de enteros como contenedor, un filtro estático y una función de reducción, y finalmente la bandera ReduceOption.

    ...
void PrimeCounter::start()
{
    if (ui->pushButton->isChecked()) {
        ui->comboBox->setEnabled(false);
        ui->pushButton->setText(tr("Cancel"));
        ui->labelResult->setText(tr("Calculating ..."));
        ui->labelFilter->setText(tr("Selected Reduce Option: %1").arg(ui->comboBox->currentText()));
        fillElementList(ui->horizontalSlider->value() * stepSize);

        timer.start();
        watcher.setFuture(
            QtConcurrent::filteredReduced(
                &pool,
                elementList,
                filterFunction,
                reduceFunction,
                currentReduceOpt | QtConcurrent::SequentialReduce));
    ...

Examinemos las funciones de filtrado y reducción. Estas funciones se declaran estáticas en este ejemplo ya que no dependen de ninguna variable miembro. Sin embargo, podrían especificarse fácilmente como lambdas o funciones miembro.

La función filter marca elementos para su posterior reducción con la función reduce. Esta implementación es un filtro primo simple. Como esta función toma una referencia const como argumento, permite un funcionamiento a prueba de hilos en el contenedor sobre el que opera.

    ...
bool PrimeCounter::filterFunction(const Element &element)
{
    // Filter for primes
    if (element <= 1)
        return false;
    for (Element i = 2; i*i <= element; ++i) {
        if (element % i == 0)
            return false;
    }
    return true;
}
    ...

La función reduce toma como primer parámetro una referencia modificable del mismo tipo que el contenedor sobre el que opera. El segundo parámetro es el elemento previamente filtrado por la función filter. En este ejemplo, contamos el número de primos.

    ...
void PrimeCounter::reduceFunction(Element &out, const Element &value)
{
    // Count the amount of primes.
    Q_UNUSED(value);
    ++out;
}
    ...

Proyecto de ejemplo @ code.qt.io

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