服务器线程和人机接口(MMI)之间的通信 [英] Communication between a server thread and a man-machine interface (MMI)
问题描述
我需要你对我现在编码的程序的建议。让我先告诉你它是什么。
设计
我正在设计一个人机界面MMI)。在这个MMI中,有两个核心元素:
-
MainWindow
:
这个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屋!