Qt Thread
-
Nochmal:
Ich habe keine AHnung was dein PortListener im Konstruktor treibt, ohne Code!!
Gib dem PortListener eine Methode "start", dann kannst du kontrollieren wann er gestartet wird.
-
Der steht doch in Post1 ;-). Ich muss das so und so ncoh ein wenig Umstrukturieren. Wenn ich z.B. auch senden möchte. Da hat serialPort auch eine Methode dafür.
Ich würde dann in der GUI einen Verbinden Button anlegen. Nur müsste ich dann am besten den Port Listener so auslegen, dass er auch senden kann. Denn sonst wird das mit dem öffnen ja Mist. Wenn ich senden will und dazu den Port erneut öffne.
-
Eigentlich könnte ich das ja auch gleich alles von Listener in SerialThread packen, oder?
-
Jan++ schrieb:
Eigentlich könnte ich das ja auch gleich alles von Listener in SerialThread packen, oder?
Weiß ich nicht
Wenn dein SerialThread nur eine Aufgabe besitzt, und zwar ein PortListener-Objekt verwalten und STarten, dann ist dies tatsächlich unnötig.
Soll dein SerialThread mal erweitert werden und nicht nur mit dem einen PortListener-Objekt arbeiten, macht es durchaus Sinn. Aber die Antwort kennst nur duIch würde auch niemals einen Listener oder sonst was gleich im Kostruktor starten, denn du willst ja sicherlich auf Ereignisse (sprich SIGNALS) warten. Wenn das Ding gleich asynchron zu werkeln anfängt kann es passieren, dass du die ersten Signals gar nicht mehr mitbekommst. Deshalb dringend angeraten:
listener = new PortListener(this); connect(listener, SIGNAL(newData()), SLOT(on_listener_newData())); listener->start();
Oder das start() gleich in QThread::run() aufrufen.
Ansonsten: Sry, aber ich erinner mich nicht an Code, wenn mir der Post oder der ganze Thread zu lange wird
-
Gesagt getan:
MainWindow::MainWindow() { setupUi(this); t1 = new SerialThread("/dev/cu.usbserial-ftDIHUS6"); t1->start(); connect(ConnectButton,SIGNAL(clicked()),t1,SLOT(openClose())); }
#ifndef SERIALTHREAD_H #define SERIALTHREAD_H #include <QThread> #include <qDebug> #include "qextserialport.h" class SerialThread : public QThread { Q_OBJECT public: SerialThread(QString name); void run(){ exec(); } private: QString portName; QextSerialPort *port; int Anzahl; private slots: void onReadyRead(); void openClose(); }; #endif // SERIALTHREAD_H
#include "SerialThread.h" SerialThread::SerialThread(QString name) { portName=name; this->port = new QextSerialPort(portName, QextSerialPort::EventDriven); port->setBaudRate(BAUD9600); port->setFlowControl(FLOW_OFF); port->setParity(PAR_NONE); port->setDataBits(DATA_8); port->setStopBits(STOP_1); } void SerialThread::onReadyRead() { QByteArray bytes; int a = port->bytesAvailable(); bytes.resize(a); port->read(bytes.data(), bytes.size()); qDebug() << "bytes read:" << bytes.size(); qDebug() << "bytes:" << bytes; Anzahl+=bytes.size(); } void SerialThread::openClose() { if(!port->isOpen()) { if (port->open(QIODevice::ReadWrite) == true) { connect(port, SIGNAL(readyRead()), this, SLOT(onReadyRead())); qDebug() << "listening for data on" << port->portName(); } else { qDebug() << "device failed to open:" << port->errorString(); } } else { port->close(); if(!port->isOpen()) { qDebug() << "port " << port->portName() << " closed"; } } }
Ein Problem hat das ganze noch. Wenn ich ConnectButton drücke. Wird nochmal ein neuer Thread gestartet. Woran liegt das?
-
Weiterhin würde mich interessieren, wie man das realisieren kann, dass erst mit dem Öffnen der Thread erzeugt wird. Und beim nochmaligen klicken auf den Verbinden Button die Schnittstelle geschlossen, und der Thread beendet wird.
-
Ich habe jetzt nochmal diese Implementierung probiert:
void SerialThread::run() { this->port = new QextSerialPort(portName, QextSerialPort::EventDriven); port->setBaudRate(BAUD9600); port->setFlowControl(FLOW_OFF); port->setParity(PAR_NONE); port->setDataBits(DATA_8); port->setStopBits(STOP_1); if (port->open(QIODevice::ReadWrite) == true) { connect(port, SIGNAL(readyRead()), this, SLOT(onReadyRead())); qDebug() << "listening for data on" << port->portName(); } else { qDebug() << "device failed to open:" << port->errorString(); } exec(); } void SerialThread::onReadyRead() { QByteArray bytes; int a = port->bytesAvailable(); bytes.resize(a); port->read(bytes.data(), bytes.size()); qDebug() << "bytes read:" << bytes.size(); qDebug() << "bytes:" << bytes; }
Da scheint etwas mit den Signalen nicht zu funktionieren, denn wenn ich ein Byte sende kommt:
bytes read: 1 bytes: "j" bytes read: 0 bytes: "" bytes read: 0 bytes: "" bytes read: 0 bytes: "" bytes read: 0 bytes: "" bytes read: 0 bytes: "" bytes read: 0 bytes: "" bytes read: 0 bytes: "" bytes read: 0 bytes: "" bytes read: 0 bytes: ""
-
Warum das jetzt so ist weiß ich nicht (hab mit QextSerialPort noch nix gemacht). Aber du kannst ja nur die empfangenen Daten verarbeiten, wenn size > 0.
Warum jetzt auf einen Button-click ein neuer Thread gestartet werden sollte erschließt sich mir aus dem Code nicht. Woher weißt denn du dass ein neuer Thread gestartet wird? Hast du da sonst noch irgend welche connects?
-
Also in dem einen habe ich keine weiteren connects. Mit dem OpenClose aber anscheinend wird wenn ich OpenClose aus dem Mainthread aufrufe implizit ein neuer Thread gestartet. Entnehmen tue ich das der Prozessanzeige im OS.
Zu dem anderen, wo die Bytes mehrmals kommen da dachte ich halt, ich habe vom Grundaufbau was falsch gemacht.
-
Also irgendwas kommt da mit den Threads durcheinander. Ich habe das ganze jetzt mal reduziert auf:
class SerialThread : public QThread { Q_OBJECT public: void run(){ qDebug() << this->thread() << QThread::currentThread(); } };
Da ist die Ausgabe: QThread(0x109f70) SerialThread(0x15dfa0)
Und ohne Q_OBJECT:
QThread(0x109f70) QThread(0x15e1c0)Und wenn ich über ein SIGNAL aus dem Hauptthread was mit einem SLOT im THREAD mache, wird das dann überhaupt im SerialThread gemacht, oder im MainThread?
-
Jan++ schrieb:
Also in dem einen habe ich keine weiteren connects. Mit dem OpenClose aber anscheinend wird wenn ich OpenClose aus dem Mainthread aufrufe implizit ein neuer Thread gestartet. Entnehmen tue ich das der Prozessanzeige im OS.
Das wäre mir neu dass ein neuer Thread als neuer Prozess angezeigt werden würde.
Das ist dann vllt. die interne Arbeitsweise des QExtSerialPort.
-
Jan++ schrieb:
Und wenn ich über ein SIGNAL aus dem Hauptthread was mit einem SLOT im THREAD mache, wird das dann überhaupt im SerialThread gemacht, oder im MainThread?
Gib mal noch qApp->thread() mit aus, das ist dein mainthread.
Du kannst das gleiche natürlich auch noch in dem SLOT ausgeben, den du connectest.
Du kannst auch mal den SerialThread verschieben, im Konstruktor.SerialThread::SerialThread() { this->moveToThread(this); }
Denn prinzipiell liegen Objekte (QObject) in dem Thread in dem sie instanziiert wurden. Mit moveToThread() kannst du sie verschieben.
-
Nein nicht neuer Prozess. Aber bei jedem Prozess stehen die Threads angegeben.
-
ohne Q_OBJECT:
QThread(0x109f70) QThread(0x15e0a0) QThread(0x109f70)mit:
SerialThread.h:13: error: 'qApp' was not declared in this scope
-
Jan++ schrieb:
mit:
SerialThread.h:13: error: 'qApp' was not declared in this scopeDu hast aber schon QApplication eingebunden (#include)?
-
So also die Dopplungen beim empfang sind jetzt weg durch:
this->moveToThread(this);
im Konstruktor. Was bewirkt das genau? Mein Konstruktor besteht ja nur aus:SerialThread(QString name) { this->moveToThread(this); portName=name; }
-
Das include hatte ich tatsächlich vergessen, in der Version:
also mit Q_OBJECT:
QThread(0x109f80) SerialThread(0x15fab0) QThread(0x109f80)ohne:
QThread(0x109f80) QThread(0x15dff0) QThread(0x109f80)
-
Und in der Abwandlung:
class SerialThread : public QThread { Q_OBJECT public: SerialThread(){ this->moveToThread(this); } void run(){ qDebug() << this->thread() << QThread::currentThread()<<qApp->thread(); } };
mit Q_OBJECT
SerialThread(0x15e170) SerialThread(0x15e170) QThread(0x109f80)ohne:
QThread(0x15e120) QThread(0x15e120) QThread(0x109f80)