サーチ…
Qtを使用する:受信者オブジェクトが信号を受信しない場合のDirectConnection
送信側のスレッドでシグナルが送信されても、接続されたスロットは呼び出されない(つまりシグナルを受信しない)場合がありますが、最終的には接続タイプQt :: DirectConnectionで問題が解決されます。問題が見つかりましたので、すべて問題ありません。
しかし、これはQtを使うのが悪い考えです:DirectConnectionは本当にこれが何であるかを知ってから、他の方法はありません。さらに詳しく説明すると、Qtによって作成された各スレッド(メインスレッドとQThreadで作成された新しいスレッドを含む)にはEventループがあり、イベントループはシグナルを受信しスレッドのアポロティアスロットを呼び出します。スロット内でブロック操作を一般的に実行することは、他のスロットが呼び出されないようにそのスレッドのイベントループをブロックするため、悪い習慣です。
イベントループをブロックすると(非常に時間のかかる操作やブロックすることによって)、イベントループがブロックされなくなるまで、そのスレッドでイベントを受信しません。ブロッキング操作がイベントループを永久にブロックする(ビジーの間など)場合、スロットを決して呼び出すことはできません。
この状況では、Qt :: DirectConnectionへの接続で接続タイプを設定することができます。イベントループがブロックされていてもスロットが呼び出されるようになりました。それがどうやってすべてを破ったのだろう? In Qt :: DirectConnectionスロットは、受信スレッドではなく、emiterスレッドで呼び出され、データの同期を破り、他の問題に遭遇する可能性があります。あなたが何をしているのか分からない限り、Qt :: DirectConnectionを使用しないでください。 Qt :: DirectConnectionを使用して問題を解決するには、あなたのコードを注意深く見て、イベントループがブロックされている理由を調べる必要があります。それはイベントループをブロックするための良い考えではなく、Qtでは推奨されません。
ここでは、問題を示す小さな例ですが、nonBlockingSlotがblockingSlotでブロックされたイベントループと呼ばれることもありますが、while(1)は不正なコーディングを示しています
class TestReceiver : public QObject{
Q_OBJECT
public:
TestReceiver(){
qDebug() << "TestReceiver Constructed in" << QThread::currentThreadId();
}
public slots:
void blockingSlot()
{
static bool firstInstance = false;
qDebug() << "Blocking slot called in thread" << QThread::currentThreadId();
if(!firstInstance){
firstInstance = true;
while(1);
}
}
void nonBlockingSlot(){
qDebug() << "Non-blocking slot called" << QThread::currentThreadId();
}
};
class TestSender : public QObject{
Q_OBJECT
public:
TestSender(TestReceiver * receiver){
this->nonBlockingTimer.setInterval(100);
this->blockingTimer.setInterval(100);
connect(&this->blockingTimer, &QTimer::timeout, receiver, &TestReceiver::blockingSlot);
connect(&this->nonBlockingTimer, &QTimer::timeout, receiver, &TestReceiver::nonBlockingSlot, Qt::DirectConnection);
this->nonBlockingTimer.start();
this->blockingTimer.start();
}
private:
QTimer nonBlockingTimer;
QTimer blockingTimer;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
TestReceiver TestReceiverInstance;
TestSender testSenderInstance(&TestReceiverInstance);
QThread receiverThread;
TestReceiverInstance.moveToThread(&receiverThread);
receiverThread.start();
return a.exec();
}