プライム・カウンター
並行処理の進行状況を監視する方法を示します。
次の例は、QFutureWatcher クラスとQt Concurrent のfilteredReduced関数を使用して、インタラクティブでノンブロッキングな QtWidgets アプリケーションを作成する方法を示しています。この例では、QList の整数を作成することができます。リストは1からnまでの自然数で自動的に埋められます。プログラムはリスト内の素数をチェックし、見つかった素数の総数を表示します。
例の実行
Qt Creator からサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Building and Running an Example を参照してください。
接続の設定
Qt Concurrentライブラリは、2 つのモードで動作するfilteredReduced関数を提供します:OrderedReduce and UnorderedReduce 。OrderedReduce
モードでは、リデュース関数は元のシーケンスの順序で呼び出され、UnorderedReduce
モードでは、要素はランダムにアクセスされます。
必要な要素でUIを構成した後、QtSignals & Slotsメカニズムを使用して、並行処理のシグナルに接続する必要があります。この例では、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 、静的フィルタと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関数を見てみよう。これらの関数はメンバ変数に依存しないため、この例では静的と宣言されています。しかし、これらはラムダやメンバ関数として簡単に指定できます。
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; } ...
©2024 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。