Communication between a server thread and a man-machine interface (MMI)

前提是你 提交于 2020-01-06 02:44:06

问题


I need your advice on a program I'm coding right now. Let me first present you what it is.

Design

I'm designing a man-machine interface (MMI). In this MMI, there are two core elements:

  • The MainWindow:

This MainWindow is the base of everything. Important: Here, I launch in a thread a server that receives the data from a client. This data is very important to the next element.

  • Supervision

This window contains a QTableWidget, the goal is to show in pseudo-real time the data received on the server in the thread of MainWindow.

The Problem

The server in the thread owned by the MainWindow receive a structure every 10 mS. How can I send these data to the Supervision window if it's open? I was thinking of using shared memory, but not really sure about this, and doesn't really which method I have to use.

Some Solutions

I tried to implement the solution of Sebastian Lange :

  • An emit in the thread Server
  • A connect in the MainWindow
  • A slot in supervision

So now my thread Server emit a signal at every frame received. But how can I do the connect in the MainWindow and how will Supervision receive the struct emit in the signal?

Here's the code of my emit:

MainWindow* MainWindow::m_psMainWindow = nullptr; // C++ 11 nullptr
void MainWindow::emit_signal_TrameRecu(StructureSupervision::T_StructureSupervision* ptr){
    emit signal_TrameRecu(ptr);
}

void MainWindow::lancerServeur(std::atomic<bool>& boolServer){
    serveur s;
    StructureSupervision::T_StructureSupervision* bufferStructureRecu;
    while(boolServer){
        bufferStructureRecu = s.receiveDataUDP();
        if(bufferStructureRecu->SystemData._statutGroundFlight != 0){
           m_psMainWindow->emit_signal_TrameRecu( bufferStructureRecu );
        }
    }
}

回答1:


Queued Connections

Qt makes cross thread communication easy when you use queued connections.

Your calls to connect should use the Qt::QueuedConnection or Qt::BlockingQueuedConnection connection types.

Custom Types in Slots and Signals

To use custom types (structs) in slots, signals, QVariant and properties you need to declare and register the type to make it available to the Qt dynamic type system.

In your header (.hpp) use Q_DECLARE_METATYPE and in your source (.cpp) use qRegisterMetaType.

Worked Example

server.hpp

#ifndef SERVER_HPP
#define SERVER_HPP
#include <QtCore>

struct customdata
{
  int id;
  QDateTime tstamp;
};
Q_DECLARE_METATYPE(customdata)

class Server : public QThread
{
  Q_OBJECT
  public:
    Server();
  signals:
    void sendData(const customdata& d);
  protected:
    virtual void run();
};

#endif

server.cpp

#include "server.hpp"

static const int customdata_metatype_id =
  qRegisterMetaType<customdata>();

Server::Server() : QThread() {}

void Server::run()
{
  customdata d;
  d.id = 0;
  for (int i = 0; i < 10; ++i)
  {
    d.id++;
    d.tstamp = QDateTime::currentDateTime();
    emit sendData(d);

    sleep(1);
  }
}

window.hpp

#ifndef WINDOW_HPP
#define WINDOW_HPP
#include <QtGui>
#include "server.hpp"

class Window : public QWidget
{
  Q_OBJECT
  public:
    Window();
  public slots:
    void receiveData(const customdata& d);
  private:
    QListWidget* mList;
};

#endif

window.cpp

#include "window.hpp"

Window::Window() : QWidget(),mList(new QListWidget())
{
  resize(400, 300);
  QVBoxLayout* mainLayout = new QVBoxLayout();
  mainLayout->addWidget(mList);
  setLayout(mainLayout);
}

void Window::receiveData(const customdata& d)
{
  QString str(QString("%1 %2").arg(d.id).arg(d.tstamp.toString()));
  mList->addItem(str);
}

main.cpp

#include <QtGui>

#include "server.hpp"
#include "window.hpp"

int main(int argc, char** argv)
{
  QApplication app(argc, argv);

  Window win;
  Server ser;

  QObject::connect(
    &ser, SIGNAL(sendData(customdata)),
    &win, SLOT(receiveData(customdata)),
    Qt::QueuedConnection);

  win.show();
  ser.start();

  return app.exec();
}

test.pro

TEMPLATE=app
QT=core gui
HEADERS=server.hpp window.hpp
SOURCES=main.cpp server.cpp window.cpp



回答2:


I once (in the days of Qt 3.2) implemented this cross thread communication using QApplication::postEvent (now QCoreApplication::postEvent). However nowadays best practise is to use promises and futures to communicate asynchronously between threads. Promises and futures has become a part of recent C++ standard and the concepts are also implemented separately as part of Qt 5 Concurrent framework. See http://qt-project.org/doc/qt-5/qtconcurrent-index.html



来源:https://stackoverflow.com/questions/24446043/communication-between-a-server-thread-and-a-man-machine-interface-mmi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!