2010-12-02 39 views
1

Je travaille sur un projet où je dois communiquer depuis mon système vers certains périphériques série RS485. La connexion elle-même fonctionne et se trouve dans un thread distinct du thread QT GUI. J'essaie d'utiliser des signaux/slots pour connecter le thread graphique au thread série qui fonctionne principalement mais chaque fois que le périphérique externe prend un peu de temps pour répondre, mon interface graphique est toujours verrouillée jusqu'à ce que le port soit terminé et je n'ai plus t été capable de comprendre comment le réparer.La connexion série lente gèle le fil QT GUI

Je commence mon fil série dans main.cpp comme ceci:

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

Comme vous pouvez le voir, l'objet de fil est de type ModbusThread qui est une sous-classe de QThread. Vous pouvez également remarquer que j'utilise Qt :: DirectConnect. J'ai essayé d'utiliser l'AutoConnect par défaut qui devrait être mis en file d'attente, car les choses en série se passent dans un autre thread mais cela ne semble pas faire de différence dans ce cas. Voici ma classe 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);  
} 

Maintenant, vous demandez peut-être ce que TxQueue fait (il est un objet répertorié dans les connexions signal/fente dans main.cpp si vous l'avez manqué). C'est une classe de file d'attente pour le type de données ModbusTransaction. L'idée est que puisque je sais que la connexion Modbus actuelle peut être occupée à un moment donné, je peux utiliser cette file d'attente comme tampon de maintien. Fondamentalement, un widget UI chargera une demande de transaction dans la file d'attente. Si la connexion Modbus est inactive, TxQueue la transmettra comme un signal à la connexion, sinon elle l'ajoutera simplement dans la file d'attente. La connexion signale TxQueue lorsqu'elle est disponible pour traiter une autre transaction via le signal busAvailable.

D'une certaine manière, il semble que TxQueue ne puisse pas accepter les transactions à ajouter à la file d'attente tant que l'objet de connexion n'est pas terminé.

je l'ai fait un peu fureter sur Google et a trouvé une page qui a recommandé que vous faites cela dans le constructeur de votre sous-classe QThread:

QObject::moveToThread(this); 

je lui ai donné un coup de feu, mais quand je lance mon pas de programme de la les signaux/slots semblent être déclenchés puisque le programme ne communique pas avec le périphérique.

regardant, peut-être que je devrais me débarrasser de ma sous-classe QThread, créez une QThread plaine puis déplacez l'objet de connexion à elle? Je suis assez nouveau avec C++ et QT donc je suis sûr qu'il y a quelque chose dans mon approche qui est un peu loin. J'apprécierais tous les conseils que vous pouvez offrir.

+0

Les connexions directes semblent erronées, vous aurez besoin de QueuedConnection lors de l'envoi de signaux à un thread différent. moveToThread (this) ne fonctionne pas, on ne peut que pousser, ne pas tirer, propriété: thread-> moveToThread (thread) devrait être correct. –

Répondre

0

QThread doit être sous-classé uniquement pour étendre le comportement du filetage. Je pense que vous devriez lire l'article suivant avant d'essayer d'utiliser la fonction moveToThread: http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

+0

J'ai lu la page que vous avez liée à et il semble dire que j'ai besoin d'utiliser un QThread régulier puis déplacez-moi ma classe ModbusConn. Cependant quand j'essaye de faire ceci je ne semble pas réellement communiquer avec l'appareil. – Smcrook

+0

Ce que je fais est ce: – Smcrook

+0

QThread * commThread = new QThread(); ModbusConn * conn = nouveau ModbusConn (0, "/ dev/ttyAM1"); commThread-> start(); conn-> moveToThread (commThread); App.connect (conn, SIGNAL (transactionComplete (ModbusTransaction)), mainWindow-> ref1, SLOT (réceptionTransaction (ModbusTransaction)), Qt :: QueuedConnection); app.connect (conn, SIGNAL (busAvailable (bool)), mainWindow-> TxQueue, SLOT (busAvailable (bool)), Qt :: QueuedConnection); app.connect (mainWindow-> TxQueue, SIGNAL (élémentUnloaded (ModbusTransaction)), conn, SLOT (executeTransaction (ModbusTransaction)), Qt :: QueuedConnection); – Smcrook