[英]How to emit cross-thread signal in Qt?
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 發送(我不確定那個,它可能是從主線程發送的,這並不重要)。
thread1 中不需要事件循環,因為發出信號不需要事件循環。 在線程 2(由 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,那么你幾乎肯定不應該繼承的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);
您可以在此信號中添加多個參數
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.