【问题标题】:Slow serial connection freezes QT GUI thread慢速串行连接冻结 QT GUI 线程
【发布时间】:2010-12-02 00:01:07
【问题描述】:

我正在做一个项目,我需要从我的系统与一些 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。我尝试使用应该排队的默认自动连接,因为串行内容正在另一个线程中进行,但就这个问题而言,这两种方式似乎都没有区别。这是我的 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 会将其作为信号传递给连接,否则只会将其添加到队列中。当 TxQueue 可以通过 busAvailable 信号处理另一个事务时,连接会向 TxQueue 发出信号。

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

我通过 google 做了一些调查,发现一个页面建议您在 QThread 子类的构造函数中执行此操作:

QObject::moveToThread(this);

我试了一下,但是当我运行我的程序时,似乎没有任何信号/插槽被触发,因为程序没有与设备通信。

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

我对 C++ 和 QT 还很陌生,所以我确信我的方法有些不妥。如果你们能提供任何建议,我将不胜感激。

【问题讨论】:

  • 直接连接看起来不对,在向不同线程发送信号时需要 QueuedConnection。 moveToThread(this) 不起作用,只能推,不能拉,所有权:thread->moveToThread(thread) 应该是正确的。

标签: multithreading qt embedded signals-slots


【解决方案1】:

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

【讨论】:

  • 我阅读了您链接到的页面,似乎是说我需要使用常规 QThread 然后将我的 ModbusConn 类移到它。但是,当我尝试这样做时,我实际上似乎并没有与设备进行通信。
  • QThread * commThread = new QThread(); ModbusConn * conn = new ModbusConn(0,"/dev/ttyAM1"); commThread->start(); conn->moveToThread(commThread); app.connect(conn, SIGNAL(transactionComplete(ModbusTransaction)), mainWindow->ref1, SLOT(receiveTransaction(ModbusTransaction)), Qt::QueuedConnection); app.connect(conn, SIGNAL(busAvailable(bool)), mainWindow->TxQueue, SLOT(busAvailable(bool)), Qt::QueuedConnection); app.connect(mainWindow->TxQueue, SIGNAL(elementUnloaded(ModbusTransaction)), conn, SLOT(executeTransaction(ModbusTransaction)), Qt::QueuedConnection);
  • 恐怕你的链接已经烂了。 (它被阻止了,我不确定这是否是由于公司安全政策造成的……)我在blog.qt.ioYou’re doing it wrong… 上找到了它。对我来说,它看起来已经被移动或迁移了,但看起来很合适......
  • 谢谢@Scheff,我已经更新了答案中的链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-03
  • 1970-01-01
  • 1970-01-01
  • 2014-12-22
  • 2012-05-12
  • 1970-01-01
  • 2010-09-20
相关资源
最近更新 更多