如何在单独的线程上设置QSerialPort? [英] How to setup QSerialPort on a separate thread?

查看:4353
本文介绍了如何在单独的线程上设置QSerialPort?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正式文档之后,我试图这样做:

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

worker-> moveToThread(thread);

//初始化连接

thread-> start();
}

Worker构造函数:

  Worker :: Worker(QObject * parent):
QObject(parent)
{
serial = new QSerialPort(this); //传递父类,应该是当前的线程
}

当我执行它抛出我这个:

  QObject:不能为不同线程的父进程创建子进程。 
(父级是QSerialPort(0x11bd1148),父级的线程是QThread(0x11bd2ef8),当前线程是QThread(0x3e47b8)


b $ b

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



同样的结果,如果我没有在构造函数中实例化串行,但是在我们调用 thread-> start()之后触发的主过程

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

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

// ...
}

我缺少什么? / p>




发送函数作为示例(插槽):

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


解决方案

坏主意使用这样的QtSerialPort模块。



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



您应该查看以下信号:


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



每当数据的有效载荷被写入设备时,发出此信号。 bytes参数设置为写入此有效内容的字节数。
bytesWritten()不会递归发出;如果你重新进入事件循环或调用waitForBytesWritten()在一个连接到bytesWritten()信号的插槽,信号将不会被重新发送(虽然waitForBytesWritten()可能仍然返回true)。




和...


void QIODevice :: readyRead()[signal]



每当新数据可用于从设备读取时,该信号被发射一次。只有当新数据可用时,例如网络数据的新有效负载到达您的网络套接字时,或当新的数据块已附加到您的设备时,它才会再次发出。



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



注意,实现从QIODevice派生的类的开发人员:你应该总是在新数据到达时发出readyRead()(不要发送它,因为仍然有数据需要在缓冲区中读取)。在其他情况下不要发射readyRead()。


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



命令行作者异步示例



命令行阅读器同步示例


Following the official documentation I'm trying to do this:

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

    worker->moveToThread(thread);

    //init connections

    thread->start();
}

Worker constructor:

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

No compiling errors but when I execute it throws me this:

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)

Namely, it's telling me that serial has as a parent the main thread and not the thread that I have created.

The same result if I don't instantiate serial in the constructor but in the main process, which is triggered after we've called thread->start():

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

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

    //...
}

What am I missing?


Send function as an example (a slot):

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

解决方案

In short, it is a bad idea to use the QtSerialPort module like this.

We designed this module based on QIODevice which already provides you non-blocking mechanism for your GUI application to use the QSerialPort class.

You should look into the following signals:

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

This signal is emitted every time a payload of data has been written to the device. The bytes argument is set to the number of bytes that were written in this payload. bytesWritten() is not emitted recursively; if you reenter the event loop or call waitForBytesWritten() inside a slot connected to the bytesWritten() signal, the signal will not be reemitted (although waitForBytesWritten() may still return true).

and...

void QIODevice::readyRead() [signal]

This signal is emitted once every time new data is available for reading from the device. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device.

readyRead() is not emitted recursively; if you reenter the event loop or call waitForReadyRead() inside a slot connected to the readyRead() signal, the signal will not be reemitted (although waitForReadyRead() may still return true).

Note for developers implementing classes derived from QIODevice: you should always emit readyRead() when new data has arrived (do not emit it only because there's data still to be read in your buffers). Do not emit readyRead() in other conditions.

I wrote two examples for doing this through the command line which you can find in here:

Command Line Writer Async Example

Command Line Reader Sync Example

这篇关于如何在单独的线程上设置QSerialPort?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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