Prinzipiell, fuer ressourcen assynchroner Natur gibt es, je nach BS, meist 2 varianten, wie man die nutzen kann, synchron und assynchron
Bei Sockets ist es per definition so !
Assynchron: steuert deine aktionen an, und wenn irgendwelche ereignisse auftreten, werden die in deinen Thread gemappt.
Synchron: das betriebssystem steuert deine Akrion an, wartet aber auf ergebnisse fuer dich. Die Dinger sehen dann aus wie synchrone funktionen.
Und wenn ein BS was ordentlich kann, dann ist es warten

Besser als man es selber implementieren kann
assynchron verwendet man tendentiell dann, wenn man sich nen eigenen thread sparen will. Alle ereignisse werden dann im mainthread abgehandelt. Wenn die verarbeitung der daten ned so lang dauert, bzw oft Luft ist zwischen ende verarbeitung und neuen empfang, langt das oft fuer ein nichtblocken der anwendung.
Erzeugt man aber mal Last, zeiht es die Oberflaeche mit runter, ergo die Anwendung wird zaeh !
Synchron verwendet man eher in einfachen abfragen, oder wenn man soweiso eigene Threads macht ....
gabe ich diesen Pollingmechanismus gemacht.
Pollen hat zwar nen schlechten ruf, ist aber oft unumgaenglich

viele Dinge realisiert das BS selber durch pollen.
Die grosse kunst beim programmieren ist das zu umgehen, und das das BS machen zu lassen, weil das kann es besser
Dies wollte ich in einem separaten Thread haben.
Durchaus verstaendlich und kein Problem
Deswegen dachte ich mir, das es am übersichtlichsten ist, das ich die ganze Socketfunktionalität in einen eigen Klasse packe.
Auch ok ....
Da man dies ja nur im Hauptthread machen darf, dachte ich das ich nun mit Signals und Slots arbeiten sollte/müsste.
Richtig, und ja Signale/Slots sind nen guter weg dazu ...
Wenn du snychron arbeitest, kannst du dir die eigene eventloop sparen.
Du leitest weiterhin QSocketEngine von QThread ab.
Erzeugst deinen Socket aber nu da wo ihn brauchst .... im richtigen Thread, ergo in der Run methode ....
Code: Alles auswählen
void QSocketEngine::run()
{
QTCPSocket mySock;
/// endlosSchleife für connectionversuche
while(!checkAbort()) /// checkAbort ist eine Funktion zum testen einer Abbruchbedingung von aussen
{
/// Versuchen zu verbinden
mySock.connect("192.168.1.50", 4000);
/// warten ob connected ! mit einstellbaren intervall
/// sehr ressourcenschonend, wenn hohe werte gewaehlt ...
if(mySock.waitForConnected(1000)) /// mal jede sekunde versuchen
{
/// wir wurden verbunden ....
/// nun einfach die daten auslesen
const char BufferSize = 512; /// Mal 512 byte als buffer nehmen
QByteArray buffer(512,0);
/// und Blockierend lesend auf den Socket Schicken
/// in ner Schleife
do
{
qint64 bytesRead = mySock.read(buffer.data(),buffer.size());
if(bytesRead > 0)
{
/// wir haben irgendwas gelesen, dass gleich an die Verarbeitungsfunktion weitergen
/// im gleichen thread wenns geht ...
/// performData(buffer.data(),bytesRead );
}
} while (!checkAbort() && /// hier eigene Abbruchbedingungen checken etc. und vielleicht auch den SocketStatus)
/// wir waren Connected und disconecten und nun, weil wir normal(oder unnormal) rausgeflogen sind ...
mySock.disconnectFromHost();
/// Gnadenfrist geben
waitForDisconnected (30000);
}
}
}
Prinzip verstanden ?
wie gesagt, die grosse kunst iss das Ding "sauber" auslaufen zu lassen.
Vorbereitet haben wir ja das ueber die checkAbort methode.
Die sollte threadsicher auf ne Variable zugreifen ...
wir definieren an der QSocketEngine eine member vom Typ bool mbAbort, die anzeigt das man abbrechen soll, und nen Mutex Um die zu schuetzen QMutex mcsAbort;
dann wuerde man sowas machen:
Code: Alles auswählen
bool QSocketEngine::checkAbort()
{
QMutexLocker(&mcsAbort);
return mbAbort;
}
void QSocketEngine::setAbort(bool bAbort = true)
{
QMutexLocker(&mcsAbort);
mbAbort = bAbort;
}
setAbort und checkAbort koennen nun von unterschiedlichen threads verwendet werden, ohne das es threadbedingt zu unsauberen verhalten kommen sollte.
Einige wuerden anmerken das der mutex überfluessig ist ... weil ne zuweissung auf nen 32bit wert zu hoher wahrscheinlichkeit ne atomare operation ist ...
Es ist aber nicht garantiert, ich bin fuer die saubere version ...
Um nun von aussen deinen Thread runterzufahren, koenntest du sowas machen ....
Code: Alles auswählen
void QSocketEngine::ShutdownConnectionThread
{
setAbort(true);
/// nun sollte parallel der Thread sich runnerfahren ...
/// ihm die Gnadenfrist geben und warten
if(!wait(10000)) /// geben wir ihm mal 10 sec
{
/// in wenn er es in der zeit nicht geschafft hat ...
/// den thread ganz boese beenden !
terminate ();
/// wir hatten ja keine andere Wahl.
/// am besten noch die Appp benachrichtigen, dass der thread ned sauber beendete und paar dinge im undefinierten zustand sind ...
/// am besten ne Exception werfen oder so !
throw(EThreadTerminated() )
}
}
Ciao ...