[英]Communicate between two qt objects in different threads through slots and signals
[英]Signals and slots between objects in different threads in Qt
基本上,我有下面的代碼:
class serverTCP : public QObject
{
// Other methods...
signals:
void newInstructions(QJsonDocument jDoc);
public slots:
void responseObtained(QJsonDocument jDoc);
}
class gatherModbus : public QObject
{
// Other methods...
signals:
void responseReady(QJsonDocument jDoc);
public slots:
void executeInstruction(QJsonDocument jDoc);
void myprocess() {
while(true)
{
// Write and read Serial Port
// Save data in json
}
};
}
void main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int netsNumber = 2; //In reality this is dynamic. It's only a example
serverTCP *server = new serverTCP;
gatherModbus * gather = new gatherModbus[netsNumber];
QThread * threads = new QThread[netsNumber];
// more necessary code...
for(int i = 0; i < netsNumber; i++)
{
gather[i].moveToThread(threads[i]);
QObject::connect(&server, SIGNAL(newInstructions(QJsonDocument)),
&gather[i], SLOT(executeInstruction(QJsonDocument)));
QObject::connect(&gather[i], SIGNAL(responseReady(QJsonDocument)),
&server, SLOT(responseObtained(QJsonDocument)));
QObject::connect(&threads[i], SIGNAL(start()),
&gather[i], SLOT(myprocess()));
// Other signals needed between the objects 'gather' and 'threads'
threads[i].start();
}
a.exec();
}
問題是對象“服務器”和“聚集”之間的連接不起作用。 對象“服務器”與“主”功能位於同一線程中,但對象“聚集”已移至其他線程。
我該怎么做才能使兩個對象都能正常通信?
我的目的是“服務器”必須能夠向所有“聚集”的對象發送信號。 在每個對象中,“聚集”必須執行插槽並返回“服務器”響應(如果有)。
如果我將連接設置為Qt::DirectConnection
插槽類型,該插槽與“ main”函數和對象“ server”在同一線程上運行,那我就不會感興趣。
任何幫助或建議,將不勝感激。
一切都在Qt文檔中。
首先,請閱讀這 。
然后,如果您不滿意,可以使用QCoreApplication::postEvent()
(有關更多信息,請點擊此處 )
信號/插槽( QObject:connect()
)和QCoreApplication::postEvent()
都是線程安全的 ,可以解決您的問題。
因此,事件和信號/插槽是完成相同任務的兩種並行機制,通常,事件將由外部實體(例如Keyboard,Mouswheel)生成,並通過QApplication中的事件循環傳遞。 通常,除非您設置代碼,否則將不會生成事件。 您可以通過QObject::installEventFilter()
過濾它們,或者通過重寫適當的函數來處理子類對象中的事件。
信號和插槽更易於生成和接收,您可以連接任何兩個QObject子類。 它們是通過元類處理的(更多信息請參見moc_classname.cpp文件),但是您將產生的大多數類間通信可能都將使用信號和插槽。 信號可以立即獲得傳遞,也可以通過隊列延遲(如果使用線程),可以生成信號
您的演示代碼似乎還可以。 這就是我們組織當前項目的方式。 如果有必要,最好提供更詳細的代碼來解釋您的問題。
順便說一句,在閱讀您的興趣之后,我建議您使用QtConcurrent模塊,該模塊似乎更適合您的興趣。
嗯...您的代碼不正確。 這是您所有麻煩的根源
void myprocess() {
while(true)
{
// Write and read Serial Port
// Save data in json
}
};
如果您要運行插槽newInstructions
和responseObtained
插槽,則myprocess不應是無限循環。 你需要 :
myprocess
,使其在完成讀寫當前可用數據后完成 QIODevice
子類(套接字,輸入流等),則信號QIODevice::readyRead()
會通知您有新數據要從設備讀取。 我懷疑您的newInstructions
應該這樣做。 myprocess
另一個調用, 以允許處理再次開始 編輯:給出您的評論,這是一種無需過多修改即可修改無限while循環的方法。
void myprocess() {
make_one_processing_round();
if(should_continue_processing())
{
QMetaObject::invokeMethod(this, &gatherModbus::myprocess, Qt::QueuedConnection);
}
};
QMetaObject :: invokeMethod將安排此方法在線程QEventLoop隊列的后面執行。 這意味着其他插槽可以執行。
我可以解決在“ myprocess”方法末尾添加下一行的問題:
QCoreApplication::processEvents(QEventLoop::AllEvents);
該方法的最終代碼如下:
void myprocess() {
while(true)
{
// Write and read Serial Port
// Save data in json
// New line:
QCoreApplication::processEvents(QEventLoop::AllEvents);
}
};
通過這一行,我知道事件將被處理。 我不知道這是否是最好的解決方案,但是它可以按需工作。
感謝大家的幫助和解答。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.