慢速串行连接冻结QT GUI线程 [英] Slow serial connection freezes QT GUI thread

查看:283
本文介绍了慢速串行连接冻结QT GUI线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我正在尝试使用信号/插槽将GUI线程连接到串行线程,大多数工作,但每当外部设备需要一点响应我的GUI仍然被锁定,直到端口完成,我还没有弄清楚如何解决它。



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

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

qDebug()<<< 用法:;
qDebug()<< -embedded:以全屏模式显示;
qDebug()<< -no-embedded:在桌面模式下显示;
qDebug()<< - 白色:将每个背景设置为白色,以进行截图。

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 *港口);
ModbusConn * m_conn;
};

#endif // MODBUSTHREAD_H

#includemodbusthread.h

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

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



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



我已经通过谷歌做了一些骗子,并发现一个页面,建议您在QThread子类的构造函数中执行此操作:

  QObject :: moveToThread(this); 

我给了一个镜头,但是当我运行我的程序没有一个信号/插槽似乎得到由于程序没有与设备进行通信,所以触发。



看看它,也许我应该摆脱我的Qthread子类,创建一个简单的Qthread然后移动连接对象对我有用[0]我会感谢你们可以提供的任何建议。

解决方案

QThread应该只是为了扩展线程行为而被子类化。我想您应该阅读以下文章,然后再尝试使用moveToThread函数: http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/


I'm working on a project where I need to communicate from my system to some RS485 serial devices. The connection itself works and is in a separate thread than the QT GUI thread.

I am trying to use signals/slots to connect the GUI thread to the serial thread which is mostly working but whenever the external device takes a bit to respond my GUI is still locked up until the port is finished and I haven't been able to figure out how to fix it.

I'm starting my serial thread in main.cpp like this:

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

As you can see, the thread object is of type ModbusThread which is a subclass of QThread. Also you may notice I'm using Qt::DirectConnect. I tried using the default AutoConnect which should be queued since the serial stuff is going on in another thread but it doesn't seem to make a difference either way in terms of this problem. Here is my ModbusThread class:

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

Now you may be wondering what TxQueue is doing (it is an object listed in the signal/slot connections in main.cpp if you missed it). That is a queue class for the ModbusTransaction datatype. The idea is that since I know that the actual modbus connection might be busy at a given time I can use this queue as a holding buffer. Basically a UI widget will load a transaction request in the queue. If the modbus connection is idle, TxQueue will pass it along as a signal to the connection otherwise it will just add it to the queue. The connection signals TxQueue when it is available to process another transaction via the busAvailable signal.

Somehow it seems like TxQueue is unable to accept transactions to be added to the queue until the connection object finishes.

I have done some sleuthing via google and found a page that recommended that you do this in the constructor of your QThread subclass:

QObject::moveToThread(this);

I gave that a shot but when I run my program none of the signals/slots seem to be getting triggered since the program isn't communicating with the device.

Looking at it, perhaps I should get rid of my Qthread subclass, create a plain Qthread then move the connection object to it?

I'm fairly new with C++ and QT so I'm sure that there's something about my approach that is a bit off. I'd appreciate any advice you guys can offer.

解决方案

QThread should be subclassed only to extend threading behavior. I think you should read the following article before trying to use the moveToThread function: http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

这篇关于慢速串行连接冻结QT GUI线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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