Qt中不同线程中对象之间的信号和槽

时间:2016-08-19 07:34:34

标签: c++ multithreading 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();
 }

问题是对象和服务器之间的连接&#39;并且&#39;聚集&#39;不工作。对象&#39;服务器&#39;与&#39; main&#39;在同一个主题中。功能,但对象&#39;收集&#39;已转移到其他线程。

我该怎样做才能使两个对象都能正常通信?

我的目的是&#39;服务器&#39;必须能够向所有对象发送信号并收集&#39;有。在每个对象中聚集&#39;必须执行插槽并返回服务器&#39;回应,如果有的话。

如果我将连接设置为与&#39; main&#39;在同一线程上运行的Qt::DirectConnection类型的插槽。功能和对象服务器&#39;这对我不感兴趣。

任何帮助或建议都将不胜感激。

4 个答案:

答案 0 :(得分:0)

所有内容都在Qt文档中。
首先,请阅读that 如果您不满意,可以使用 QCoreApplication::postEvent() (了解您需要的更多信息: here

信号/广告位(QObject:connect())和QCoreApplication::postEvent()都是线程安全的,可以解决您的问题。

因此事件和信号/槽是实现相同事物的两个并行机制,通常事件将由外部实体(例如键盘,Mouswheel)生成,并将通过QApplication中的事件循环传递。通常,除非您设置代码,否则您将不会生成事件。您可以通过QObject::installEventFilter()过滤它们,或者通过覆盖相应的函数来处理子类对象中的事件。

信号和插槽更容易生成和接收,您可以连接任何两个QObject子类。它们是通过Metaclass处理的(有关更多信息,请查看您的moc_classname.cpp文件),但您将生成的大多数类间通信可能会使用信号和插槽。信号可以立即传递或通过队列延迟传递(如果使用线程)可以生成信号

答案 1 :(得分:0)

您的演示代码似乎没问题。这就是我们组织当前项目的方式。如有必要,您最好提供更详细的代码来解释您的问题。

BTW,在阅读了您的兴趣之后,我建议您使用QtConcurrent模块,它似乎更符合您的兴趣。

答案 2 :(得分:0)

嗯......你的代码不行。这是你所有麻烦的来源

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队列的后面安排此方法执行。这意味着其他插槽可以执行。

答案 3 :(得分:0)

我可以在“myprocess”方法的末尾添加下一行来解决我的问题:

QCoreApplication::processEvents(QEventLoop::AllEvents);

此方法的最终代码是:

void myprocess() {
            while(true)
            {
                 // Write and read Serial Port
                 // Save data in json 

                 // New line:
                 QCoreApplication::processEvents(QEventLoop::AllEvents);
            }
       };

通过这一行我得到的事件将被处理(如果有的话)。我不知道它是否是最好的解决方案,但它可以按原样运行。

感谢各位的帮助和解答。