10

ボタン用のスロットがあり、スレッドを開始する単純なフォーム UI があります。

void MainWindow::LoadImage()
{
    aThread->run();
}

run() メソッドは次のようになります。

void CameraThread::run()
{
    qDebug("Staring Thread");
    while(1)
    {
        qDebug("ping");
        QThread::sleep(1);
    }
}

LoadImage() を呼び出すボタンをクリックすると、UI が応答しなくなります。デバッグ出力として「ping」メッセージが定期的に表示されますが、UI がハングし、何も応答しません。スレッドが個別に実行されないのはなぜですか? パブリック QThread として派生した CameraThread は、Ubuntu 10.04 (x86) リポジトリの QT ライブラリと QT Creator で gcc バージョン 4.4.3 (Ubuntu 4.4.3-4ubuntu5) を使用しています。

4

3 に答える 3

33

簡単な答え:aThread->start(); notを呼び出してスレッドを開始し、run()スレッドの run() メソッドが保護されている (公開されていない) ことを確認します。

説明

呼び出しstart()はスレッドを開始する正しい方法です。run()呼び出しは優先度のスケジューリングを提供し、独自のスレッド コンテキストでメソッドを実際に実行するためです。

このスレッドで画像をロードする予定のようです。QThread の使用中に多くの人が陥る落とし穴に遭遇する前に、いくつかのヒントを含めます。

  1. QThread 自体はスレッドではありません。これは単なるスレッドのラッパーであり、これにより..
  2. クラスで定義されたシグナル/スロットは、CameraThread必ずしもスレッドのコンテキストで実行されるとは限りません。 run() メソッドとそこから呼び出されるメソッドのみが別のスレッドで実行されていることに注意してください。

私見ですが、ほとんどの場合、QThread をサブクラス化することは適切ではありません。次のコードを使用すると、はるかに簡単に実行でき、多くの頭痛の種から解放されます。

class ImageLoader : public QObject {
Q_OBJECT
public slots:
    void doWork() 
    {
        // do work
    }
};

void MainWindow::MainWindow(/*params*/) 
{
  ImageLoader loader;
  QThread thread;
  loader.moveToThread( &thread );
  connect( this, SIGNAL( loadImage() ), &loader ,SLOT( doWork() ) );
  thread.start();
  // other initialization
}
void MainWindow::LoadImage()
{
   emit loadImage();
}

このトピックに関するQt ブログもお読みください。

于 2010-07-09T15:15:07.793 に答える
5

run ではなく thread->start() を呼び出す必要があります... run はスレッドのエントリ ポイントです。スレッドは start で開始されます。直接実行を呼び出すため、GUIをブロックします。QThread のドキュメントを確認してください。virtual void QThread::run() は保護されています (理由がないわけではありません)

于 2010-07-09T14:58:54.153 に答える
-1

問題は、コンストラクターで QtCore.QThread._init__(self) を呼び出していない可能性があると思います。同じ問題がありました。また、start 関数をオーバーライドするべきではなく、run() 関数をオーバーライドするだけでよいと思います。これにより、私が抱えていたのと同じ問題が解決しました。sleep() の遅延がなくても、ウィンドウは応答するはずです。

于 2010-07-11T03:02:49.850 に答える