このページでは

プライムカウンター

並行処理の進行状況を監視する方法を示します。

以下の例では、QFutureWatcher クラスと Qt Concurrent。この例では、ユーザーはサイズ変更可能な整数のQList を作成できます。リストには、1からnまでの自然数が自動的に格納されます。その後、プログラムはリスト内の素数をチェックし、見つかった素数の総数を表示します。

「reduce」オプションセレクタ、スタートボタン、進行状況バー、および素数カウント結果を備えた素数カウンター

例の動作

以下の手順で例を実行できます:

接続の設定

この Qt Concurrent このライブラリは、OrderedReduce and UnorderedReduce の2つのモードで動作するfilteredReduced関数を提供しています。OrderedReduce モードでは、縮小関数は元のシーケンスの順序で呼び出されますが、UnorderedReduce モードでは、要素はランダムにアクセスされます。

必要な要素で UI を構成したら、Qtのシグナル&スロット機構を使用して、それらを並行操作のシグナルに接続する必要があります。この例では、QFutureWatcher クラスを使用して並行操作の進行状況を監視し、対話型 GUI を実装するために必要なシグナルを提供します。

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

QFutureWatcher クラスは、並行処理の変化に応じてUIを更新するために必要なシグナルを提供するため、この例において極めて重要な役割を果たします。

並行処理の開始

すべてのシグナルとスロットの接続が完了した後、ユーザーが QPushButton を押すと、start() 関数が呼び出されます。

start() 関数内では、Qt Concurrent のfilteredReduced関数を呼び出し、QFutureWatcher メンバーにfutureを設定します。この操作が真に並行して実行されるようにするため、最初のパラメータとして別のQThreadPool を指定します。このアプローチにより、グローバルスレッドプールでのブロックも回避できます。 コンテナとして整数のQList を渡し、静的なfilter関数とreduce関数、そして最後に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));
    ...

filter関数とreduce関数を詳しく見てみましょう。これらの関数は、メンバー変数に依存していないため、この例ではstaticとして宣言されています。ただし、ラムダ式やメンバー関数として指定することも容易です。

filter関数は、後のreduce関数による集約処理の対象となる要素をマークします。この実装は、単純な素数フィルタです。この関数は引数としてconst参照を受け取るため、操作対象のコンテナに対してスレッドセーフな処理を行うことができます。

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

reduce関数は、操作対象のコンテナと同じ型の変更可能な参照を最初のパラメータとして受け取ります。2番目のパラメータは、filter関数によって事前にフィルタリングされた要素です。この例では、素数の個数を数えています。

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

サンプルプロジェクト @ 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.