服务器线程和人机接口(MMI)之间的通信 [英] Communication between a server thread and a man-machine interface (MMI)

查看:227
本文介绍了服务器线程和人机接口(MMI)之间的通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要你对我现在编码的程序的建议。让我先告诉你它是什么。



设计



我正在设计一个人机界面MMI)。在这个MMI中,有两个核心元素:




  • MainWindow



    li>


这个MainWindow是一切的基础。 重要:在这里,我在一个线程中启动从客户端接收数据的服务器。这些数据对下一个元素非常重要。




  • 监督






此窗口包含一个 QTableWidget ,目标是以伪实时方式显示在MainWindow的线程中在服务器上接收的数据。



问题



MainWindow 每10 mS接收一个结构。如果该窗口打开,我如何将这些数据发送到 Supervision 窗口?我正在考虑使用共享内存,但不是真正确定这一点,而不是真正的方法我必须使用。



一些解决方案



我尝试实现Sebastian Lange的解决方案:




  • >
  • 在MainWindow中连接

  • 在监管中插槽



所以现在我的线程 Server 在每个帧接收到一个信号。但是如何在MainWindow中执行连接,并且 Supervision 如何在信号中接收 struct 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);
}
}
}


解决方案>

排队的连接>

当您使用排队的连接时,Qt使交叉线程通信变得容易。



您对 connect 的调用应使用 Qt :: QueuedConnection Qt :: BlockingQueuedConnection 连接类型。



插槽和信号中的自定义类型



要在插槽,信号,QVariant和属性中使用自定义类型(结构),您需要<



在您的标题(.hpp)中使用 href =http://qt-project.org/doc/qt-4.8/qmetatype.html#Q_DECLARE_METATYPE =nofollow> Q_DECLARE_METATYPE 和在您的来源(.cpp)中使用 qRegisterMetaType



工作示例



server.hpp

  #ifndef SERVER_HPP 
#define SERVER_HPP
#include< QtCore>

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

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

#endif

server.cpp / p>

  #includeserver.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 / p>

  #ifndef WINDOW_HPP 
#define WINDOW_HPP
#include< QtGui>
#includeserver.hpp

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

#endif

window.cpp / p>

  #includewindow.hpp

Window :: Window():QWidget (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)。 id).arg(d.tstamp.toString()));
mList-> addItem(str);
}

main.cpp
$ b

  #include< QtGui> 

#includeserver.hpp
#includewindow.hpp

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

窗口赢;
服务器ser;

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

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

return app.exec();
}

test.pro
$ b

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


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 );
        }
    }
}

解决方案

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

这篇关于服务器线程和人机接口(MMI)之间的通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆