2

現在、Qt のシグナルとスロットがスレッドでどのように動作するかを理解しようとしています。

次のコードで小さなテストを実行しようとしました。

class Worker : public QObject{
    Q_OBJECT
public:
    Worker(int _value){value = _value;}
    ~Worker(){};
    int value;

public slots:
    void changeValue(int newValue){value = newValue;}
    void doWork(){
        while(1){
            _sleep(500);
            std::cout << "Value is " << value << std::endl;
            if(value == 0)break;
        }
        emit finished();
    }

signals:
    void finished();
};

class Manager : public QObject{
    Q_OBJECT
public:
    Manager(){}
    ~Manager(){};
signals:
    void modifiedValue(int value);
public:
    void changeTheValue(int value){emit modifiedValue(value);}
};

基本的に、ワーカーはvalueメンバーを時々表示し、値を変更する機能を持つスロットを持っています。

manager は、 が呼び出されたときに新しい値を持つシグナルを発行する唯一の目的を持ちます。これは、メンバーchangeTheValueを変更する Worker のスロットにマップされます。value

次にWorker、次の方法でクラスをスレッドで機能させます。

QThread myThread;
Worker myWorker(10);
Manager manager;

myWorker.moveToThread(&myThread);
QObject::connect(&myThread, SIGNAL(started()), &myWorker,SLOT(doWork()));
QObject::connect(&myWorker, SIGNAL(finished()), &myThread, SLOT(quit()));
QObject::connect(&myWorker, SIGNAL(finished()), &myWorker, SLOT(deleteLater()));
QObject::connect(&myThread, SIGNAL(finished()), &myThread, SLOT(deleteLater()));
QObject::connect(&manager, SIGNAL(modifiedValue(int)), 
                 &myWorker, SLOT(changeValue(int)));
myThread.start();

for(int i = 1; i < 10 ; i++){
    _sleep(1000);
    manager.changeTheValue(i);
}
manager.changeTheValue(0);

しかし、何も起こりません。値は変更されていないようです: 出力にはValue is 10.

私が理解できないのは、シグナル/スロット マッピングがManager::modifiedValueと でWorker::changeValue機能していないように見えるのはなぜですか? doWork()スレッドが現在ループを実行しているためだけですか? スロットへの呼び出しはどこで終了しますか (キューに入れられた、破棄された、その他) ?

シグナル/スロットメカニズムがスレッドでどのように機能するかについて、これ以上見つけることができませんでした(どのスレッドのコールスタックがスロットへの呼び出しを終了するかを説明するこのスレッドしか見つかりませんでしたが、回答で提供されたリンクは古くなっているようですQt 5 ホームにつながります)。

質問を要約するには:

  • 値を変更するスロットへの呼び出しが何もしないのはなぜですか?
  • これを機能させることは可能ですか (必要に応じてスレッドセーフを追加します)、どのように?
4

1 に答える 1

3

シグナルとスロットがスレッドでどのように機能するかには、複数のモードがあります (QThreadこれらを機能させるには、絶対に s を使用する必要があります!)。これらはマニュアルに記載されています: http://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-threads

コードの間違いは、Qt イベント ループが呼び出されないことです (doWork決して返されないため)。繰り返し呼び出しの場合、そのスレッドでタイマーを使用する必要があります。processEventsまたは(推奨される解決策ではありません) 、無限ループで呼び出すことができます。

于 2013-05-27T14:27:06.150 に答える