7

QThreadを強制終了/キャンセルしようとしています。https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/の実装に従いました

次のようにQThreadを作成します。

workerThread = new QThread();
ImageProcessor* worker = new ImageProcessor();
worker->moveToThread(workerThread);
connect(workerThread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), workerThread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
workerThread->start();

次のコマンドを呼び出して、特定のUIイベントで停止してみてください。

workerThread->quit();

私の労働者は次のようになります:

class ImageProcessor : public QObject
{
Q_OBJECT
public:
explicit ImageProcessor(QObject *parent = 0);
~ImageProcessor();

signals:
void finished();

public slots:
void process();

private:
//...
};

プロセスが大量の計算でAPIを呼び出す場所

void ImageProcessor::process()
{
// API call...

emit finished();
}

私の問題は、スレッドでquitを呼び出した後、スレッドが実行を継続することです。つまり、APIの計算が停止しません。ワーカーはAPIを呼び出すだけなので、ワーカーループでキャンセルチェックを行うことはできません。何か案は?

前もって感謝します!

4

5 に答える 5

2

あなたの重い仕事はとても単純なのでQtConcurrent::run、QThread を使って忘れてしまいます。

ImageProcessor* worker = new ImageProcessor();
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
QtConcurrent::run(worker, &ImageProcessor::process);

これはまさに必要なことを行い、新しいスレッドを作成する代わりにスレッドプールからスレッドを使用するため、さらに高速になります。

使用することを忘れないでQt::AutoConnectionください(デフォルト値)。

正常に処理を停止するには、プロセス メソッドでいくつかの変数のポーリングを行う必要があります。

bool ImageProcessor::needEndNow() {
    QMutexLocker locker(mutex);
    return endNowRequested;
}

void ImageProcessor::requestEndNow() {
    QMutexLocker locker(mutex);
    endNowRequested = true;
}

void ImageProcessor::process()
{
   while(!needEndNow()) {
       // nextStep of processing
   }

   emit finished();
}
于 2013-08-07T12:21:35.910 に答える
1

少なくとも安全な方法では、ブロックされた QThread を停止することはできません。

たとえば、この関数を入力した場合

void neverStop() {
    int *arr = new int[1024*1024];
    for (;;) {
    }
}

スレッドは終了メッセージに応答しません。また、ほとんどの OS にはスレッドを強制的に終了させる方法がありますが、割り当てられたメモリは適切に解放されません。

于 2013-01-06T15:41:05.370 に答える
1

つまり、API の計算は停止しません。

それで、計算中にそれを止めようとしますか?

QThread::quit は、すべてが計算された後にのみ停止します。

計算を小さなタスクに分割したり、キャンセル フラグを追加したりすることもできます。それを設定する ImageProcessor オブジェクトに通常のメソッドを用意します。

class ImageProcessor{
   void stop(){
     canceled = true;
   }
private:
   bool canceled;
}

次に、(キャンセルされた)リターンかどうかを確認します。プロセススロットで。(書き込み専用の bool は一種のスレッドセーフです)

次に、stop(); を呼び出します。オブジェクトで、スレッドで quit() を実行します。

于 2013-01-06T11:55:41.120 に答える
0

使用する代わりに、thread->quit()(セマポアの概念に適応して) 処理ループ内にキャンセル フラグを含める必要があります。これにより、たとえば処理を停止して finished() シグナルを発行することにより、ワーカーを内部から適切に停止することができます。

slot_cancelWorker()ワーカー内にキャンセル用のスロット (例: ) を実装することで、フラグを設定できます。次に、それを GUI に接続できます。

connect(myPushButton, SIGNAL(clicked()), worker, SLOT(slot_cancelWorker()));

もちろん、処理関数内では、保留中のイベントをチェックする必要があります。したがって、QCoreApplication::processEvents()定期的に電話する必要があります。

于 2013-08-07T11:41:42.463 に答える