Seite 1 von 1

QSockets, QThreads, Non-Blocking auf die Daten warten

Verfasst: 1. März 2007 22:36
von nik_28
Grüßgottle,
ich habe Schwierigkeiten mit der Handhabung von QSockets in Verbindung mit QThreads (Beides Qt 2.3). Ich versuche mal, mein Problem zu erklären, bei Bedarf schicke ich gerne Quellcode mit.

Beschreibung
Ich habe eine Client-Klasse mit einem QSocket. Normalerweise schicke ich über das Socket eine Anfrage an den Server, er soll mir bitte 3D-Daten schicken (die ich dann später auf dem Client darstellen möchte).
Dann passiert kurz nichts, bis die Daten kommen. Kurze Zeit später wird automatisch das Signal "readyRead()" aufgerufen, weil die Daten beim Socket 'anklopfen'. Daraufhin rufe ich beim Client eine read()-Methode auf, die die Daten einliest. Diese wird meist mehrmal aufgerufen, weil die Daten für einen Schub zu groß sind.

Das Problem
So weit so gut.

Nun möchte ich aber immer neue 3D-Daten einlesen (und diese teilweise gegen alte austauschen), gleichzeitig aber die schon vorhandenen Daten darstellen.
Ich öffne also einen neuen Thread. Da muss man dann synchronisieren und so weiter (ich behaupte mal das wäre erledigt).

Jetzt kommt meine Frage:
Mit meinem neuen Thread schicke ich eine Anfrage für die neuen 3D-Daten, die ich gerade benötige.
Weil ich unbedingt warten muss, bis alle neuen Daten vollständigig eingelesen sind, bevor ich in diesem Thread fortfahren darf (damit ich keine inkonsistenten Zustände kriege), schreibe ich ein:
a)

Code: Alles auswählen

qwaitcond.wait()
b)

Code: Alles auswählen

usleep(1000);
c)

Code: Alles auswählen

qsocket.waitForMore(1000);
Leider tut's nicht
Ist aber alles nicht so geschickt, denn
bei c) blockiert der Thread, es ist also ein "busy waiting". Während des wartens kann sonst niemand was tun.
Bei b) könnten meines Erachtens andere Threads weiterarbeiten. Wenn ich dann immer mit qsocket.bytesAvailable() gucke, ob schon was da ist, verschwenden wir nicht viel Zeit.
Aber: So lange man schläft, wird kein Signal "readyRead()" emmitiert. Nix kommt am Socket an, komischerweise.
Bei a) Lande ich in einem Deadlock. Auch hier kommt nichts mehr am socket an, daher kann man die QWaitCondition nicht mehr lösen.

Zugegeben, die drei Vorschläge erscheinen mir selbst auch noch nicht besonders hübsch, bisher fiel mir aber nichts anderes ein.

Gibt es tolle Ideen/Musterbeispiele/Standardlösungen?
Kommen jemandem die Probleme bekannt vor?

Vielen Dank im Voraus,
Niklas
[/b]

Verfasst: 2. März 2007 12:00
von nik_28
Ich habe mir gerade sagen lassen, das Problem kann man gar nicht lösen.

So lange ich nämlich in einer Funktion warte, ist die Event-Loop unterbrochen. An die komme ich innerhalb meiner Funktion nicht ran, auch nicht in einem neu gestarteten Thread.

D.h. die Katze beißt sich in den Schwanz, weil ich in meiner Funktion auf etwas warte, was durch die Ausführung meiner Funktion verhindert wird. Sone Art deadlock.

(Falls jetzt jemand behauptet, es geht doch, höre ich trotzdem gerne zu...)

Verfasst: 2. März 2007 12:09
von macman
http://doc.trolltech.com/2.3/qapplication.html#30e70c
Wird aber wirklich langsam Zeit für eine neuere Qt-Version.

Verfasst: 2. März 2007 14:35
von nik_28
Dankeschön,

genau das hatte ich gerade auch probiert:

Code: Alles auswählen

qApp->processEvents(maxtime);
(das meintest du, oder? Ist der Aufruf so korrekt?)

Leider hat er sich gerade wieder in einem Deadlock verfangen. Ich friemel mal ein bisschen an der 'maxtime' herum, vielleicht tut sich dann noch was.

An der qt-Version bin ich unschuldig! Ich bin nur der arme Leidtragende...

Verfasst: 2. März 2007 14:57
von nik_28
Im Grunde ist das wohl schon die richtige Idee, es lassen sich sogar die Menüs bedienen etc., nur mein Socket will nicht.

Mit der while-Schleife ist das vielleicht nicht so die feine Art, aber tun sollte es ja eigentlich:

Code: Alles auswählen

/// wait for network to send segment
void SegmentMeshClient::waitForSegment(int si)
{
	while (getSegTetraMeshP()->refSegment(si).loaded != true)
	{
		qApp->processEvents();
	}
}
Wenn man ein in die Schleife ein .bytesAvailable() einfügt sagt er, da wäre nichts am Socket, obwohl der Server hoch und heilig verspricht, dass er alles abgeschickt (und geflushed) hat.