慢速串行连接冻结QT GUI线程

时间:2010-12-02 00:01:07

标签: multithreading qt embedded signals-slots

我正在开展一个项目,我需要从我的系统与一些RS485串行设备进行通信。连接本身可以工作,并且位于与QT GUI线程不同的线程中。

我正在尝试使用信号/插槽将GUI线程连接到主要工作的串行线程,但每当外部设备需要一点响应时,我的GUI仍然被锁定,直到端口完成且我没有能够找出解决方法。

我在main.cpp中启动我的串行线程,如下所示:

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QFile f(":/TS-Controls.qss");
    if (f.open(QIODevice::ReadOnly)) {
        app.setStyleSheet(f.readAll());
        f.close();
    }

    for (int i = 0; i < argc; ++i) {
        if (QString(argv[i]) == QString("-h") ||
            QString(argv[i]) == QString("--help") ||
            QString(argv[i]) == QString("-help")) {

            qDebug() << "Usage:";
            qDebug() << " -embedded : show in fullscreen mode";
            qDebug() << " -no-embedded : show in desktop mode";
            qDebug() << " -white : Set every background to white for screenshots. ";

            return 0;
        }
    }
    MainWindow* mainWindow = new MainWindow();
    ModbusThread * thread = new ModbusThread("/dev/ttyAM1");
    app.connect(thread->m_conn, SIGNAL(transactionComplete(ModbusTransaction)), mainWindow->ref1, SLOT(receiveTransaction(ModbusTransaction)), Qt::DirectConnection);
    app.connect(thread->m_conn, SIGNAL(busAvailable(bool)), mainWindow->TxQueue, SLOT(busAvailable(bool)), Qt::DirectConnection);
    app.connect(mainWindow->TxQueue, SIGNAL(elementUnloaded(ModbusTransaction)), thread->m_conn, SLOT(loadTransaction(ModbusTransaction)), Qt::DirectConnection);

    thread->start();

    mainWindow->show();
    return app.exec();
}

如您所见,线程对象的类型为ModbusThread,它是QThread的子类。你也可能注意到我正在使用Qt :: DirectConnect。我尝试使用默认的AutoConnect,它应该排队,因为串口的东西正在另一个线程中进行,但它在这个问题方面似乎没有任何区别。这是我的ModbusThread类:

    #include <QThread>
#include <modbusconn.h>
#include <modbustransaction.h>

#ifndef MODBUSTHREAD_H
#define MODBUSTHREAD_H

class ModbusThread : public QThread
{
public:
    ModbusThread(char * port);
    ModbusConn * m_conn;
};

#endif // MODBUSTHREAD_H

#include "modbusthread.h"

ModbusThread::ModbusThread(char * port) : QThread()
{
    this->m_conn = new ModbusConn(this, port);       
}

现在您可能想知道TxQueue正在做什么(如果您错过了它,它是main.cpp中信号/插槽连接中列出的对象)。这是ModbusTransaction数据类型的队列类。我的想法是,因为我知道实际的modbus连接在给定时间可能很忙,所以我可以将此队列用作保持缓冲区。基本上,UI小部件将在队列中加载事务请求。如果modbus连接处于空闲状态,TxQueue会将其作为信号传递给连接,否则它只会将其添加到队列中。当可通过busAvailable信号处理另一个事务时,连接信号TxQueue。

不知何故,在连接对象完成之前,似乎TxQueue无法接受要添加到队列的事务。

我已经通过谷歌进行了一些调查,并找到了一个页面,建议您在QThread子类的构造函数中执行此操作:

QObject::moveToThread(this);

我给了那个镜头,但是当我运行我的程序时,由于程序没有与设备通信,所以没有任何信号/插槽被触发。

看着它,也许我应该摆脱我的Qthread子类,创建一个普通的Qthread,然后将连接对象移动到它?

我对C ++和QT相当新,所以我确信我的方法有点不对劲。我很感激你们提供的建议。

1 个答案:

答案 0 :(得分:0)

QThread应仅被子类化以扩展线程行为。我想你应该在尝试使用moveToThread函数之前阅读以下文章:http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/