Multithreading 使用2个线程在串行端口上同时读写
在Qt中,是否可以从两个不同的线程同时读取和写入同一个串行端口?。由于它的实现(与Qt的任何I/O类相同),不可能从不同的线程执行读/写操作。QSP使用非阻塞(异步)I/O,允许从一个线程“同时”进行读/写操作。而不是直接进行。在Multithreading 使用2个线程在串行端口上同时读写,multithreading,qt,Multithreading,Qt,在Qt中,是否可以从两个不同的线程同时读取和写入同一个串行端口?。由于它的实现(与Qt的任何I/O类相同),不可能从不同的线程执行读/写操作。QSP使用非阻塞(异步)I/O,允许从一个线程“同时”进行读/写操作。而不是直接进行。在port上调用的任何方法都必须在port.thread()中调用。否则就是未定义的行为:您可以格式化硬盘驱动器 但是,您可以通过使用信号槽机制间接地实现这一点。与其在端口上调用方法,不如使用一个接口类作为端口的线程安全接口: struct PortInterface :
port
上调用的任何方法都必须在port.thread()中调用。否则就是未定义的行为:您可以格式化硬盘驱动器
但是,您可以通过使用信号槽机制间接地实现这一点。与其在端口上调用方法,不如使用一个接口类作为端口的线程安全接口:
struct PortInterface : QObject {
Q_SIGNAL void writeData(const QByteArray &);
Q_SIGNAL void hasReadData(const QByteArray &);
Q_OBJECT
};
int main(int argc, char ** argv) {
QApplication app(argc, argv);
PortInterface interface;
QSerialPort port;
QObject::connect(&interface, &PortInterface::writeData, &port, [&](const QByteArray &data){
qDebug() << "writing in thread" << QThread::currentThread();
Q_ASSERT(QThread::currentThread() == port.thread());
port.write(data);
});
QObject::connect(&port, &QIODevice::readyRead, [&]{
qDebug() << "reading in thread" << QThread::currentThread();
Q_ASSERT(QThread::currentThread() == port.thread());
emit interface.hasReadData(port.readAll());
});
您可以将任意数量的对象附加到hasReadData
信号。这些对象可以存在于任何线程中。回想一下,信号插槽连接属于1:n
类型,其中0No,但无论您认为需要做什么,都很可能出错。当然,数据可以来自任何您想要的地方,但是QSerialPort
方法的调用必须都来自与port->thread()
@Kuba Ober相同的线程,我明白了。但问题是。我试图演示串行端口在一个线程上读取,在GUI线程上显示。为了测试这一点,我需要不断地写入串行端口,同时需要从串行端口读取相同的数据并显示在GUI线程上。我试图在一台机器(我的笔记本电脑)上演示所有这些。所以我想在我的应用程序中有3个线程。1个主GUI线程、1个读卡器线程、1个写卡器线程。读卡器和写卡器必须是同一个线程。考虑到串行端口的速度相对较慢,与CPU/内存带宽相比,将作业分为两个线程会使情况变得更糟,而不是更好:多线程的开销高于使串行端口始终充满数据以及处理任何回复所需的作业。@Kuba Ober,当应用程序在一台机器(我的笔记本电脑)上运行时,任何时候都不能让多个应用程序使用串行端口。所以,我试图知道是否有多个线程可以在任何时候使用串行端口。我看不出这是怎么回事。我想说的是,您需要从线程访问串行端口。它可以是任何线程:它可以是gui线程,也可以是专用线程。没关系。但是它只能是一个线程:port.thread()
的值。这并不意味着不能从其他线程向该线程传递数据,或者提取数据并将其传递到其他线程。这只意味着直接在QSerialPort
上完成的调用必须全部从端口的线程完成。之后,您可以在多个线程之间传递该数据!你能帮我把这段代码整理成一个Qt项目吗?至于上面代码的哪一部分去了哪里?@Aham想象一下,散文(描述性文本)不在那里。将代码片段粘在一起,您将得到一个可以编译的main.cpp
。因为端口未打开,所以它不会有多大作用,但在其他方面它是完整的。
QTimer sourceTimer;
sourceTimer.start(20);
QObject::connect(&sourceTimer, &QTimer::timeout, [&]{
qDebug() << "timer tick in thread" << QThread::currentThread();
interface.writeData(QByteArray(20, 'd'));
});
QObject::connect(&interface, &PortInterface::hasReadData, &app, [&](const QByteArray &data){
qDebug() << "data read in thread" << QThread::currentThread();
qDebug() << data.toHex();
});
QThread sourceThread, portThread;
QThread::currentThread()->setObjectName("mainThread");
sourceThread.setObjectName("sourceThread");
portThread.setObjectName("portThread");;
sourceTimer.moveToThread(&sourceThread);
port.moveToThread(&portThread);
sourceThread.start();
portThread.start();
return app.exec();
}