簡體   English   中英

Qt中不同線程中對象之間的信號和插槽

[英]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 
       }
};

如果您要運行插槽newInstructionsresponseObtained插槽,則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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM