Hallo Leute.
Ich habe ein sehr umfangreiches, auf Qt basierendes, RPC Protokoll geschrieben. Ich kann damit bei Bedarf blockieren und warten, bis die Antwort von meinem Server kommt. Das blockeren übernehme ich mit QEventLoop. Es funktioniert fast alles wie ich es auch erwarte und wünsche, ABER wenn ich meine Abfrage in einem SLOT ausführe, scheint es mir meine anderen Signale zu blockieren. Mein QTcpSocket sendet readyRead nicht mehr. Ich habe zum testen mein tcpsocket auch mal in einem Thread laufen lassen, leider ohne Besserung.
Ich habe jetzt wirklich alles ausprobiert.
* Synchrone Abfrage an irgendeiner Stelle im Code (bis auf SLOTS) >> funktioniert wunderbar.
* Synchrone Abfrage in einem SLOT >> readyRead wird nicht mehr ausgelöst.
[gelöst] Problem mit blockender Funktion im Slot
[gelöst] Problem mit blockender Funktion im Slot
Zuletzt geändert von dazedly am 26. November 2010 12:53, insgesamt 1-mal geändert.
Re: Problem mit blockender Funktion im Slot
hmm.. drei Dinge:
1. "Warten"
Du kannst im Sourcecode von Qt auch abschauen, denn:
http://doc.qt.nokia.com/4.7/qtest.html#qWait
macht sowas bereits.
2. "Signal in Slot"
2. "Thread ist gescheitert"
.. aber ohne Code können wir natürlich nicht sagen was. Meine Vermutung wäre, dass du "moveToThread()" vergessen hast..
hth!
1. "Warten"
Meinst du das so ähnlich wie bei QTcpSocket: es gibt Signals aber bei bedarf kann auch "waitFor......()" genommen werden? Da startest du aber nicht eine NEUE Eventloop, oder? Dafür müsstest du einfach eine wait-Methode machen, welche mit processEvents() noch Signals durchlässt.dazedly hat geschrieben:Ich kann damit bei Bedarf blockieren und warten, bis die Antwort von meinem Server kommt. Das blockeren übernehme ich mit QEventLoop.
Du kannst im Sourcecode von Qt auch abschauen, denn:
http://doc.qt.nokia.com/4.7/qtest.html#qWait
macht sowas bereits.
2. "Signal in Slot"
Wie soll denn dein Programm ein Signal versenden, wenn du gerade was tust (=dich in einem Slot und nicht in der Eventloop befindest)? Mit anderen Worten: deine Beobachtung ist natürlich richtig und kann auch gar nicht anderst sein...dazedly hat geschrieben: Es funktioniert fast alles wie ich es auch erwarte und wünsche, ABER wenn ich meine Abfrage in einem SLOT ausführe, scheint es mir meine anderen Signale zu blockieren.
2. "Thread ist gescheitert"
Dann würde ich sagen: du hast das falsch gemachtdazedly hat geschrieben: Ich habe zum testen mein tcpsocket auch mal in einem Thread laufen lassen, leider ohne Besserung.
hth!
Ich könnte das tcp socket blockieren lassen, aber wie ich schon geschrieben habe, soll das bei Bedarf passieren. Der TcpSocket soll immernoch auf Nachrichten vom Server lauschen. Ich benötige eine bidirektional Verbindung und diese darf nicht blockieren. Ich verwalte meine Pakete in einer Map, welche nach den RequestIDs der Pakete indiziert ist. Wenn etwas neues kommt, überprüfe ich, ob es eine Antwort auf eines meiner Pakete ist. Der Server kann genauso wie der Client Requests schicken.
Zum Thema Thread:
Da ich die Klasse in der das QTcpSocket erstell wird, von QThread abgeleitet hatte, bin ich auch davon ausgegangen, dass die Signale mit dazu gehören. Ich werde das jetzt noch einmal versuchen, aber habe nicht die große Hoffnung.
Nachtrag:
Hier geht es um eine permanente Verbindung. Die Clients müss sich beim Server Athentifizieren und bekommen und laufen dort in einem eigenen Thread. Der Thread ist ein Objekt, welches wieder abgeleitet ist von QThread. In diesem Objekt sind die Benutzerdaten des Clients gespeichert und dieser hat nur auf bestimmte Funktionen zugriff. Alle Threads werden von einer Map verwaltet und über diese können bei Bedarf die Clients miteinander synchronisiert werden. Der Server funktioniert ohne Probleme und macht genau das, was er soll.
Zum Thema Thread:
Da ich die Klasse in der das QTcpSocket erstell wird, von QThread abgeleitet hatte, bin ich auch davon ausgegangen, dass die Signale mit dazu gehören. Ich werde das jetzt noch einmal versuchen, aber habe nicht die große Hoffnung.
Nachtrag:
Hier geht es um eine permanente Verbindung. Die Clients müss sich beim Server Athentifizieren und bekommen und laufen dort in einem eigenen Thread. Der Thread ist ein Objekt, welches wieder abgeleitet ist von QThread. In diesem Objekt sind die Benutzerdaten des Clients gespeichert und dieser hat nur auf bestimmte Funktionen zugriff. Alle Threads werden von einer Map verwaltet und über diese können bei Bedarf die Clients miteinander synchronisiert werden. Der Server funktioniert ohne Probleme und macht genau das, was er soll.
Zuletzt geändert von dazedly am 26. November 2010 12:56, insgesamt 1-mal geändert.
Code: Alles auswählen
Client::getInstance()->sendRonsPacket(bla);
this->loop->exec();
return this->result; Die Lösung dazu habe ich unter Punkt 1. bereits beschrieben: du musst eine eigene Wait-Methode schreiben so im Stil:
Code: Alles auswählen
do {
while(QCoreApplication::hasPendingEvents())
QCoreApplication::processEvents(); // ermoegliche readyRead()
seep(nur_ganz_kurz_z_B_10ms)
pruefeEndedesRPC()
} while (rpc_not_finished or timeout)
Das gibt alle paar Wochen Probleme hier... Lesen-Lesen-Lesen (Doku und hier im Forum).Da ich die Klasse in der das QTcpSocket erstell wird, von QThread abgeleitet hatte, bin ich auch davon ausgegangen, dass die Signale mit dazu gehören. Ich werde das jetzt noch einmal versuchen, aber habe nicht die große Hoffnung.
Eine elegante Methode ist: http://labs.qt.nokia.com/2006/12/04/thr ... -headache/
Hier stimmen dann auch deine Annahmen...
Auf der Serverseite (QTcpServer) ist zu beachten, dass QTcpServer sich selbst als Parent setzt und daher ein "moveToThread()" fehlschlägt. Also zuerst "socket->setParent(NULL)" und danach moveToThread().
Wenn du die letzten beiden Sätze nicht verstehst, ist es noch zu früh für Multithreading... dann empfehle ich dir, Threads ausserhalb deines Projektes in einem kleineren Rahmen zuerst in Betrieb zu nehmen.
hth!
Ich habe meinen Fehler gefunden....
zu:
Vielen Dank für deine Hilfe und deine Lösungsvorschläge haben mich in das Thema Qt noch weiter hinein befördert, auch wenn jeder versuchte Fix völlig unnötig war.
Code: Alles auswählen
connect(this->tcpSocket,SIGNAL(readyRead()),SLOT(readDataSlot()),Qt::DirectConnection);
Code: Alles auswählen
connect(this->tcpSocket,SIGNAL(readyRead()),SLOT(readDataSlot()),Qt::QueuedConnection);