如何在单独的线程上设置QSerialPort?

时间:2014-05-09 08:09:04

标签: c++ qt qthread qtcore qtserialport

按照官方文档,我正在尝试这样做:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    QThread *thread = new QThread;    
    Worker *worker= new Worker();

    worker->moveToThread(thread);

    //init connections

    thread->start();
}

工作者构造函数:

Worker::Worker(QObject *parent) :
    QObject(parent)
{
    serial = new QSerialPort(this);  //passing the parent, which should be the current thread      
}

没有编译错误但是当我执行它时会抛出这个:

QObject: Cannot create children for a parent that is in a different thread. 
(Parent is QSerialPort(0x11bd1148), parent's thread is QThread(0x11bd2ef8), current thread is QThread(0x3e47b8)

也就是说,它告诉我serial作为父线程的主线程而不是我创建的线程。

如果我没有在构造函数中实例化serial,而是在主进程中实例化相同的结果,这在我们调用thread->start()后触发:

Worker::Worker(QObject *parent) :
    QObject(parent)
{             
}

Worker::doWork()
{
    if(!serial)
        serial= new QSerialPort(this); 

    //...
}

我错过了什么?


发送功能作为示例(插槽):

void Worker::send(const QByteArray &data)
{
    serial->write(data);
    if( serial->waitForBytesWritten(TIMEOUT) )
        qDebug() << "sent: " << data;
}

1 个答案:

答案 0 :(得分:7)

简而言之,像这样使用QtSerialPort模块是一个坏主意。

我们基于QIODevice设计了这个模块,它已经为您的GUI应用程序提供了使用QSerialPort类的非阻塞机制。

您应该查看以下信号:

  

void QIODevice::bytesWritten(qint64 bytes) [signal]

     

每次将数据有效负载写入设备时都会发出此信号。 bytes参数设置为在此有效负载中写入的字节数。   bytesWritten()不是递归发出的;如果重新进入事件循环或在连接到bytesWritten()信号的槽内调用waitForBytesWritten(),则不会重新发送信号(尽管waitForBytesWritten()仍然可以返回true)。

和...

  

void QIODevice::readyRead() [signal]

     

每当有新数据可供设备读取时,此信号就会发出一次。只有在新数据可用时才会再次发出,例如网络数据的新有效负载已经到达您的网络套接字,或者新的数据块已经附加到您的设备上。

     

readyRead()不是递归发出的;如果你重新进入事件循环或在连接到readyRead()信号的槽内调用waitForReadyRead(),则不会重新发送信号(尽管waitForReadyRead()仍然可以返回true)。

     

对于实现从QIODevice派生的类的开发人员的注意事项:当新数据到达时,您应该始终发出readyRead()(仅因为仍有待在缓冲区中读取数据而不发出它)。不要在其他条件下发出readyRead()。

我通过命令行写了两个例子,你可以在这里找到:

Command Line Writer Async Example

Command Line Reader Sync Example