Seite 1 von 1
QThread kommunikation
Verfasst: 8. August 2011 11:43
von DBGTMaster
Hallo,
Folgende Situation:
- Habe meinen QThread nun in einer Event- Loop am laufen.
- Der MainThread soll den QThread mitteilen, dass er einen bestimmten Slot aufrufen soll.
- Der MainThread soll warten, bis dieser Slot abgearbeitet ist und je nach Antwort dann weiter arbeiten...
Wie realisiere ich soetwas am besten??
1.) Wie kann ich den QThread mitteilen, dass er einen Slot sofort ausführen soll, ohne dass ich eine Signal, Verbindung herstellen muss? Gibts hierfür eine Methode??
2.) Woher weiß ich, wann dieser Slot fertig ausgeführt wurde??
lG
Re: QThread kommunikation
Verfasst: 8. August 2011 12:24
von Christian81
Gar nicht - Busy Wait im Hauptthread ist nicht wirklich sinnvoll da die komplette GUI blockiert...
Re: QThread kommunikation
Verfasst: 8. August 2011 12:28
von solarix
Es gibt natürlich auch "traditionelle" Methoden (ohne Qt) dafür, aber ich empfinde die Qt-Variante mit Signal/Slots wesentlich einfacher..Daher: Warum keine (zwei) Signal/Slot-Connections (eine für den Auftrag, eine für das Resultat)? Falls man die GUI in dieser Zeit blockieren möchte, kann das problemlos via QSplashScreen geschehen (wobei man sich dann fragen sollte, wozu überhaupt ein Thread genommen wird):
1. In einem Slot der GUI (z.B. auf Button-Click): QSplashScreen Erstellen und Anzeigen und Signal für Job emitten (an Thread)
2. Im Thread den Job erledigen und das Resultat emitten (an Slot in GUI-Thread)
3. Im Slot der GUI Resultat in Empfang nehmen und QSplashScreen schliessen.
hth..
Re: QThread kommunikation
Verfasst: 8. August 2011 12:52
von DBGTMaster
Ok, so hab ich mir das auch schon fast gedacht...
Und wie sende ich am besten sofort ein Ereignis, um den Slot im Thread auszuführen??
über QTimer::singleShot(0) ??
lG
Re: QThread kommunikation
Verfasst: 8. August 2011 13:13
von DBGTMaster
Beim QTimer steh ich nun vor folgendem Problem:
Code: Alles auswählen
QTimer::singleShot(0, tcpThread, SLOT(connectTcpServer(QString,quint16)));
Wie übergebe ich diesen nun die Parameter??
Oder soll ich diese über Methoden setzen (setHostname(), setPort() ), und einen leeren Slot einrichten??
Re: QThread kommunikation
Verfasst: 8. August 2011 13:27
von solarix
Warum denn keine Signal/Slot-Connection von der GUI zum Thread? Dann musst du in der GUI nur noch emitten...
Hin und wieder nutze ich auch "interne" Signals eines Objektes.. z.B.
Code: Alles auswählen
Thread::Thread(..
{
connect(this, SIGNAL(job(...)), this, SLOT(...)), Qt::QueuedConnection);
}
void Thread::job(args) {
emit doJob(args); // Signal/Slot zu sich selbst
}
...
void Gui::btnXyClicked()
{
thread->job(...);
}
dann entfällt das für die GUI.. ist besonders hilfreich, wenn man mehrere solche "Worker"-Threads hat.
hth..
Re: QThread kommunikation
Verfasst: 8. August 2011 13:53
von DBGTMaster
Also, wenn ich das nun richtig verstanden habe:
QThread Objekt:
Code: Alles auswählen
class TcpMainThread : public QThread {
public:
void connectTcpServer(QString hostname, quint16 port);
public slots:
void runConnectTcpServer(QString hostname, quint16 port);
signals:
void doConnectTcpServer(QString hostname, quint16 port);
}
Und der Konstruktor:
Code: Alles auswählen
TcpMainThread::TcpMainThread(QObject *parent) :
QThread(parent)
{
moveToThread(this);
// ...
// ...
// Eigen- Signale / Slots einrichten...
// Tcp- Verbindung herstellen:
connect(this, SIGNAL(doConnectTcpServer(QString,quint16)),
this, SLOT(runConnectTcpServer(QString,quint16)) );
}
Der MainThread ruft nun die connectToServer() Methode auf, diese wirft ein Signal (doConnectToServer), welches dann wiederrum im eventloop des threads die runConnectToServer() aufruft..
So korrekt

?
lG
// Edit: Das einzige, was ich noch änderen werde, ist, dass ich die Signal / Slot- Prozedur in eine eigene Klasse auslagern werde, damit die Thread Klasse selber sich auf das eigentliche konzentrieren kann, um übersicht zu behalten...
Re: QThread kommunikation
Verfasst: 8. August 2011 14:35
von solarix
ganz genau
übrigens: QTcpServer ist bereits multithreaded..eigentlich braucht man bei Bedarf nur noch Threads für die einzelnen TCP-Verbindungen, nicht jedoch für den Server...
[EDIT] Moment du scheinst da ja ein Client zu haben.. nicht ein Server. Trotzdem: Für den TCP-Client selbst braucht man übrigens auch nur selten ein Thread (nur dann, wenn das Protokoll sehr aufwendig ist..), weil der auch wieder bereits threaded ist..
hth!
Re: QThread kommunikation
Verfasst: 8. August 2011 14:43
von DBGTMaster
solarix hat geschrieben:ganz genau
übrigens: QTcpServer ist bereits multithreaded..eigentlich braucht man bei Bedarf nur noch Threads für die einzelnen TCP-Verbindungen, nicht jedoch für den Server...
hth!
Das ganze ist auch kein Server, sondern ein Client... Und diesen Lagere ich in einen eigenen Thread ab, damit dieser in Ruhe seine TCP- Anfragen erledigen kann sowie auf seine Antworten warten usw...
Bin gerade dabei, ein Framework zu bauen, um Tcp und GUI komplett zu trennen

... Und zwar nach dem Prinzip:
Code: Alles auswählen
TcpCommand_Login* login = TcpMainThread::instance()->newCommand<TcpCommand_Login>();
login->setUsername( ui->inputUsername->text() );
login->setPassword( ui->inputPassword->text() );
connect(login, SIGNAL(loginDone(TcpCommands::userLoginResponse),
this, SLOT(loginDone(TcpCommands::userLoginResponser)));
login->start();
Und der TcpThread sendet dann den Server die Logindaten, wartet auf die Antwort des Servers, verarbeitet diese und sendet diese der GUI zurück..
lG
Re: QThread kommunikation
Verfasst: 8. August 2011 15:02
von solarix
DBGTMaster hat geschrieben:
Das ganze ist auch kein Server, sondern ein Client... Und diesen Lagere ich in einen eigenen Thread ab, damit dieser in Ruhe seine TCP- Anfragen erledigen kann sowie auf seine Antworten warten usw...
Ja, ich weiss. habe das im [EDIT] berichtig.. Ich wiederhole auch gerne nochmals, dass man QTcpSockets "im Normalfall" (was auch immer das in der Softwareentwicklung bedeutet

)
nicht threaded braucht, weil die Sockets
bereits threaded sind. Oder mit anderen Worten: warum soll (m)eine Applikation 2x warten: das erste mal im Qt-Thread und das zweite mal nochmal in (m)einem Thread..
hth!
Re: QThread kommunikation
Verfasst: 8. August 2011 15:13
von DBGTMaster
solarix hat geschrieben:DBGTMaster hat geschrieben:
Das ganze ist auch kein Server, sondern ein Client... Und diesen Lagere ich in einen eigenen Thread ab, damit dieser in Ruhe seine TCP- Anfragen erledigen kann sowie auf seine Antworten warten usw...
Ja, ich weiss. habe das im [EDIT] berichtig.. Ich wiederhole auch gerne nochmals, dass man QTcpSockets "im Normalfall" (was auch immer das in der Softwareentwicklung bedeutet

)
nicht threaded braucht, weil die Sockets
bereits threaded sind. Oder mit anderen Worten: warum soll (m)eine Applikation 2x warten: das erste mal im Qt-Thread und das zweite mal nochmal in (m)einem Thread..
hth!
Hallo,
aber in meinen Anwendungsfall ist threaded einfach nötig, da ich ansonsten meine Anwendung blockieren würde, mein Framework will es einfach so
Aber danke für deine Hilfe

Re: QThread kommunikation
Verfasst: 8. August 2011 15:55
von solarix
DBGTMaster hat geschrieben:
aber in meinen Anwendungsfall ist threaded einfach nötig, da ich ansonsten meine Anwendung blockieren würde
Naja.. genau das wolltest du ja eingangs ("Der MainThread soll warten").. aber belassen wir es dabei, du wirst schon wissen was du brauchst
Ich hab noch was vergessen:
Code: Alles auswählen
// Eigen- Signale / Slots einrichten...
// Tcp- Verbindung herstellen:
connect(this, SIGNAL(doConnectTcpServer(QString,quint16)),
this, SLOT(runConnectTcpServer(QString,quint16)) );
Ich würde da explizit "QueuedConnection" nehmen.. vermutlich würde die "AutoConnection" schon funktionieren ("If the signal is emitted from a different thread than the receiving object, the signal is queued"), aber weil du da nichts anderes als eine QueuedConnection brauchst, würde ich das auch explizit wählen.. Ausserdem ist da die Doku IMHO nicht 100% exakt (meint "thread" nun thread-"context" oder -"affinity"?)
hth
Re: QThread kommunikation
Verfasst: 8. August 2011 16:05
von DBGTMaster
solarix hat geschrieben:DBGTMaster hat geschrieben:
aber in meinen Anwendungsfall ist threaded einfach nötig, da ich ansonsten meine Anwendung blockieren würde
Naja.. genau das wolltest du ja eingangs ("Der MainThread soll warten").. aber belassen wir es dabei, du wirst schon wissen was du brauchst
Ich hab noch was vergessen:
Code: Alles auswählen
// Eigen- Signale / Slots einrichten...
// Tcp- Verbindung herstellen:
connect(this, SIGNAL(doConnectTcpServer(QString,quint16)),
this, SLOT(runConnectTcpServer(QString,quint16)) );
Ich würde da explizit "QueuedConnection" nehmen.. vermutlich würde die "AutoConnection" schon funktionieren ("If the signal is emitted from a different thread than the receiving object, the signal is queued"), aber weil du da nichts anderes als eine QueuedConnection brauchst, würde ich das auch explizit wählen.. Ausserdem ist da die Doku IMHO nicht 100% exakt (meint "thread" nun thread-"context" oder -"affinity"?)
hth
Ok, werd ich hinzufügen :=)
lG
Re: QThread kommunikation
Verfasst: 8. August 2011 17:30
von solarix
Bin gerade zufälligerweise auf genau dieses Detail in der (Thread)-Doku gestossen:
Also musst du da
unbedingt eine QueuedConnection nehmen.. denn die Thread-Affinität ist in deinem Fall die gleiche (der "this"-Pointer (sender) hat die gleiche Affinität wie der "this"-Pointer (Empfänger)). Die daraus resultierende DirectConnection würde jedoch bewirken, dass der Slot im GUI-Thread aufgerufen würde.. nicht das, was du möchtest..
hth!