[gelöst]QThread ohne exec() - keine Signals werden ausgelöst

Alles rund um die Programmierung mit Qt
Antworten
Konk
Beiträge: 13
Registriert: 23. März 2007 15:26

[gelöst]QThread ohne exec() - keine Signals werden ausgelöst

Beitrag von Konk »

Meine kleine Applikation soll über TCP/IP einen Ethernet-RS232-Konverter ansprechen, was in einer "Standalone"-Demo auch sehr gut funktioniert.
Jetzt habe ich eine GUI dazu gebastelt und die Kommunikation in einen separaten Thread ausgelagert. Ich leite von QThread ab und überschreibe die run() Methode. Dort verbinde ich mich mit dem Konverter mittels

Code: Alles auswählen

pTcpSocket->connectToHost("192.168.0.3", 10001);
Wenn ich nun mit

Code: Alles auswählen

QAbstractSocket::SocketState state = pTcpSocket->state();
den Status Abfrage, ist dieser "QAbstractSocket::ConnectingState".
Und da bleibt er auch. Das connected() Signal wird nie ausgelöst.


Folgendes habe ich schon ausprobiert, was aber nicht geholfen hat:

- Den Socket als Membervariable anlegen, statt einer lokalen Variable in run().

- Das connect()

Code: Alles auswählen

connect( &tcpSocket, SIGNAL(connected()), this, SLOT(conEstablishedSlot()));
im Konstruktor meiner abgeleiteten Threadklasse oder in run() platziert.
Da in run() ein neuer Thread erzeugt wird, habe ich auch probiert, statt dem this Pointer einen Pointer auf die Instanz des abgeleiteten Threads zu übergeben. Trotzdem kein Signal.

- Connects mit/ohne Qt::DirectConnection als fünften Parameter.

Das einzige was funktioniert ist, wenn ich in run() die Funktion exec() aufrufe.
Aber wo soll ich dann meine Programmlogik einbauen?
(Es soll alle x Sekunden ein String versendet und einer (über das readyRead() Signal) empfangen werden)

Vielleicht ist auch mein Design verbesserungswürdig.
Wenn jemand eine Idee hat, alles ist herzlich willkommen.
Zuletzt geändert von Konk am 29. Mai 2007 19:50, insgesamt 1-mal geändert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

exec() startet die Eventloop, also ist es nötig.
Für den Rest - einfach einen QTimer und/oder auf irgendwelche Signals reagieren. Wie im 'normalen' Programm eben auch.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Konk
Beiträge: 13
Registriert: 23. März 2007 15:26

Beitrag von Konk »

Danke für die Nachricht.
An Timer hab ich auch schon gedacht, nur wo erstelle ich diesen bzw wie wird er verdrahtet. Mache ich den Timer als Member und will ihn in run() vor exec() starten, sagt Qt:
QObject::startTimer: timers cannot be started from another thread

Erstelle ich den Timer als lokale Variable in run() und möchte dessen Signal mit einem Slot verbinden

Code: Alles auswählen

	QTimer* timer = new QTimer(this);
	connect(timer, SIGNAL(timeout()), this, SLOT(dummySlot()));
	timer->start();
sagt er:
QObject: Cannot create children for a parent that is in a different thread.
Object::connect: No such slot ComThread::dummySlot()
Egal ob ich this oder einen Pointer auf den Thread, der run() aufruft übergebe.

Und wie beende ich den laufenden Thread sauber wieder? Mit terminate() werden angeblich die Ressourcen nicht sauber freigegeben. In meinem Qt Buch ist leider nur ein Thread Bsp ohne exec()-Aufruf.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

da geht nur QTimer *timer = new QTimer()

this ist im Hauptthread, der timer wird aber im neu erzeugten Thread erstellt -> parent muss im gleichen Thread sein -> deshalb kann der QTimer als parent nicht this haben.

--> QTimer *m_timer als member-Variable, create in run(), delete in dtor
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Konk
Beiträge: 13
Registriert: 23. März 2007 15:26

Beitrag von Konk »

Ok, aber wie sieht dann der connect aus? Der braucht als dritten Parameter den Receiver. "This" ist der Hauptthread - muss ich also einen Pointer auf diesen übergeben?
z.B.

Code: Alles auswählen

connect(p_timer, SIGNAL(timeout()), m_pMainThread, SLOT(dummySlot()));
Das connect muss im run() stattfinden, außerhalb ist p_timer null.

Wenn ich es so implementiere, sagt Qt zur Laufzeit:
Object::connect: No such slot QThread::dummySlot()
Wie kann ich ihm beibringen welchen Slot er verwenden soll?
Grüße
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Konk hat geschrieben: Object::connect: No such slot QThread::dummySlot()
Wie kann ich ihm beibringen welchen Slot er verwenden soll?
Indem Du es richtig angibst... :)
m_pMainThread muss schon ein Pointer der Klasse sein, welche den Slot dummySlot() implementiert. So wie es aussieht ist m_pMainThread vom Typ QThread* und/oder deiner Klasse fehlt ein Q_OBJECT
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Zandru
Beiträge: 84
Registriert: 29. Mai 2007 15:35

Beitrag von Zandru »

Du kannst auch statt exec() regelmässig processEvents() aufrufen.
Konk
Beiträge: 13
Registriert: 23. März 2007 15:26

Beitrag von Konk »

Vielen Dank für den Tipp mit processEvents(). Das hab ich in meine Schleife in run() eingefügt, jetzt scheint es alles zu funktionieren.

Zu der anderen Lösung:
pMainThread war ein QThread* - dem fehlte natürlich der Slot. Mit

Code: Alles auswählen

ComThread* m_pMainThread;
im Header und

Code: Alles auswählen

m_pMainThread = this;
im Konstruktor klappt die Verbindung jetzt auch.
Vielen Dank Euch beiden.
Antworten