使用2个线程在串行端口上同时读写

时间:2016-11-28 14:31:26

标签: multithreading qt

在Qt中,是否可以同时从2个不同的线程读取和写入相同的串口?

2 个答案:

答案 0 :(得分:2)

不直接。您在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());
  });

您可以在任何线程中调用writeData方法:Qt的信号槽机制将包装调用并安全地将其传递到端口的线程。同样,可以从任何线程调用hasReadData信号。 readAll调用是从端口自己的线程完成的。处理可用数据的代码应该连接到该插槽。

因此,我们可以在专用线程中使用一个定时器来将一些数据写入端口,我们可以在主线程中有一个侦听新数据的插槽:

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

您可以将任意数量的对象附加到hasReadData信号。这些对象可以存在于任何线程中。回想一下,信号槽连接是1:n种,其中0<=n

类似地,您可以让任意数量的对象调用接口的writeData方法:只要他们写入的数据是一个独立的数据包,就可以保证数据包将在端口作为一个单元,不与其他数据包交错。但接收方必须能够描述数据包:数据包需要标头或其他同步方式(例如HDLC)。

当然你需要先打开端口:)

答案 1 :(得分:1)

不。由于其实现,不可能从不同的线程进行读/写(与Qt的任何I / O类相同)。 QSP使用非阻塞(异步)I / O,允许从一个线程使用读/写&#34;同时&#34;。