Qtのドキュメントでは、シグナルとスロットはdirect
、queued
、auto
にできると述べています。
また、スロットを所有するオブジェクトが信号を所有するオブジェクトとは異なるスレッドで「生きている」場合、そのような信号を発信することはメッセージを投稿するようなものであり、信号発信は即座に戻り、スロットメソッドはターゲットスレッドのイベントループで呼び出されます。
残念ながら、ドキュメンテーションでは、「ライブ」が表すことを指定しておらず、使用可能な例はありません。私は次のコードを試しました:
_main.h:
_
_class CThread1 : public QThread
{
Q_OBJECT
public:
void run( void )
{
msleep( 200 );
std::cout << "thread 1 started" << std::endl;
MySignal();
exec();
}
signals:
void MySignal( void );
};
class CThread2 : public QThread
{
Q_OBJECT
public:
void run( void )
{
std::cout << "thread 2 started" << std::endl;
exec();
}
public slots:
void MySlot( void )
{
std::cout << "slot called" << std::endl;
}
};
_
_main.cpp:
_
_int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
CThread1 oThread1;
CThread2 oThread2;
QObject::connect( & oThread1, SIGNAL( MySignal() ),
& oThread2, SLOT( MySlot() ) );
oThread1.start();
oThread2.start();
oThread1.wait();
oThread2.wait();
return a.exec();
}
_
出力は次のとおりです。
_thread 2 started
thread 1 started
_
MySlot()
が呼び出されることはありません:(。何が間違っていますか?
コードにはかなりの問題があります:
このコードはおそらく動作するでしょう(私はテストしていません)。
class MyObject : public QObject
{
Q_OBJECT
public slots:
void MySlot( void )
{
std::cout << "slot called" << std::endl;
}
};
class CThread1 : public QThread
{
Q_OBJECT
public:
void run( void )
{
std::cout << "thread 1 started" << std::endl;
int i = 0;
while(1)
{
msleep( 200 );
i++;
if(i==1000)
emit MySignal();
}
}
signals:
void MySignal( void );
};
class CThread2 : public QThread
{
Q_OBJECT
public:
void run( void )
{
std::cout << "thread 2 started" << std::endl;
exec();
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
CThread1 oThread1;
CThread2 oThread2;
MyObject myObject;
QObject::connect( & oThread1, SIGNAL( MySignal() ),
& myObject, SLOT( MySlot() ) );
oThread2.start();
myObject.moveToThread(&oThread2)
oThread1.start();
return a.exec();
}
これで、MyObjectはthread2に存在します(moveToThreadに感謝)。
MySignalはthread1から送信する必要があります(その1つについては定かではありませんが、メインスレッドから送信される可能性がありますが、実際には問題ではありません)。
シグナルの送信にはイベントループは必要ないため、thread1ではイベントループは必要ありません。シグナルを受信するには、thread2(exec()によって待機)でイベントループが必要です。
MySlotはthread2で呼び出されます。
Aiuaの答えは良いですが、QThreadとQt 4.6または4.7のいくつかの問題を指摘したいと思います。
この記事は要約します: http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/
残念なことに、問題はドキュメントの更新が不足していることに起因しています。 Qt 4.4より前のQThreadにはデフォルトのrun()実装がありませんでした。つまり、使用するためにQThreadをサブクラス化する必要がありました。
Qt 4.6または4.7を使用している場合、ほぼ確実にnotサブクラスQThreadを使用する必要があります。
ワーカースレッドで実行するスロットを取得するための鍵は、Aiuaが指摘したようにmoveToThreadメソッドを使用することです。
次のようなスレッド関数を開始するためのシグナルを発行する必要があります
emit operateCut(examId,examName_examTemplate[examName].studentIdRec,examName_examTemplate[examName].choiceRecA,examName_examTemplate[examName].choiceRecB,examName_examTemplate[examName].objectRecA,examName_examTemplate[examName].objectRecB);
このシグナルに複数の引数を追加できます