Auf dieser Seite

Prime-Zähler

Veranschaulicht, wie man den Fortschritt von parallel laufenden Vorgängen überwacht.

Das folgende Beispiel zeigt, wie man mithilfe der Klasse ` QFutureWatcher ` und der Funktionen ` filteredReduced ` aus Qt Concurrent. Mit diesem Beispiel kann der Benutzer eine „ QList “ aus ganzen Zahlen erstellen, deren Größe angepasst werden kann. Die Liste wird automatisch mit natürlichen Zahlen von 1 bis n gefüllt. Das Programm sucht anschließend in der Liste nach Primzahlen und zeigt die Gesamtanzahl der gefundenen Primzahlen an.

Primzahlzähler mit Auswahlfeld für die Reduzierungsoption, Start-Schaltfläche, Fortschrittsbalken und Ergebnis der Primzahlzählung

Ausführen des Beispiels

Sie können das Beispiel wie folgt ausführen:

Einrichten der Verbindungen

Die Qt Concurrent Bibliothek bietet die „filteredReduced “-Funktionen, die in zwei Modi betrieben werden können: „ OrderedReduce and UnorderedReduce “. Im Modus „ OrderedReduce “ wird die Reduktionsfunktion in der Reihenfolge der ursprünglichen Sequenz aufgerufen, während im Modus „ UnorderedReduce “ der Zugriff auf die Elemente zufällig erfolgt.

Nachdem die Benutzeroberfläche mit den gewünschten Elementen konfiguriert wurde, müssen diese mithilfe des Qt-Signals-&-Slots-Mechanismus mit den Signalen der parallelen Operationen verbunden werden. In diesem Beispiel verwenden wir die Klasse „ QFutureWatcher “, um den Fortschritt der parallelen Operationen zu überwachen und die für die Implementierung der interaktiven Benutzeroberfläche erforderlichen Signale bereitzustellen.

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

Die Klasse „ QFutureWatcher “ spielt in diesem Beispiel eine entscheidende Rolle, da sie die Signale bereitstellt, die erforderlich sind, um die Benutzeroberfläche als Reaktion auf Änderungen bei den parallelen Operationen zu aktualisieren.

Starten des parallelen Vorgangs

Nachdem alle Signals & Slots verbunden wurden und der Benutzer auf die Schaltfläche „QPushButton“ klickt, wird die Funktion „ start() “ aufgerufen.

In der Funktion ` start() ` rufen wir die Funktion `filteredReduced ` aus ` Qt Concurrent ` auf und setzen den `Future` auf das Mitglied ` QFutureWatcher `. Um sicherzustellen, dass dieser Vorgang wirklich parallel läuft, geben wir als ersten Parameter einen separaten ` QThreadPool ` an. Dieser Ansatz verhindert zudem mögliche Blockierungen im globalen Thread-Pool. Wir übergeben die ` QList ` mit Ganzzahlen als Container, eine statische Filter- und Reduce-Funktion sowie schließlich das Flag ` 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));
    ...

Betrachten wir die Filter- und Reduzierfunktionen. Diese Funktionen sind in diesem Beispiel als statisch deklariert, da sie nicht von einer Member-Variablen abhängen. Sie könnten jedoch problemlos als Lambdas oder Member-Funktionen definiert werden.

Die Filterfunktion markiert Elemente für die anschließende Reduktion durch die Reduce-Funktion. Bei dieser Implementierung handelt es sich um einen einfachen Primzahlfilter. Da diese Funktion eine `const`-Referenz als Argument entgegennimmt, ermöglicht sie eine threadsichere Bearbeitung des Containers, auf den sie angewendet wird.

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

Die Funktion `reduce` nimmt als ersten Parameter eine veränderbare Referenz desselben Typs wie der Container, auf dem sie arbeitet. Der zweite Parameter ist das zuvor von der Funktion `filter` gefilterte Element. In diesem Beispiel zählen wir die Anzahl der Primzahlen.

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

Beispielprojekt @ 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.