Nic Geschrieben May 8, 2012 at 09:50 Geschrieben May 8, 2012 at 09:50 Die beiden Threads RecvLoop und CallbackLoop in der IPConnection-Klasse sind für das Auswerten der Rückantworten der Devices zuständig ? Arbeiten diese parallel zum Hauptthread nur solange, bis die Devices hinzugefügt wurden und werden abschließend beendet ? Oder bleiben beide suspended ? Ich würde das Prinzip gerne verstehen, um es passend in Delphi zu portieren. Zitieren
photron Geschrieben May 8, 2012 at 09:59 Geschrieben May 8, 2012 at 09:59 Der RecvLoop läuft dauerhaft, liest alles was am Socket ankommt und behandelt es passend. Der CallbackLoop ist dafür da die Callbacks auszuführen, so dass man aus Callbacks heraus auch noch Getter der Devices aufrufen kann. Würden der RecvLoop die Callbacks ausführen würde dieser ja in der Zeit keine eingehenden Packages mehr annehmen können und wir hätten ein Deadlock, da die Antwort des Devices auf den Getter Aufruf nicht gelesen würde. Das ganze kommuniziert miteinander über thread-sichere Queues. Zitieren
Nic Geschrieben May 8, 2012 at 10:51 Autor Geschrieben May 8, 2012 at 10:51 Der Thread des RecvLoop läuft dauerhaft ? Wenn ja was triggert den Einsprung ? Oder bewirkt das die interne Endlos-Schleife while(RecvLoopFlag) solange das Flag true bleibt ? Wenn ich einen Breakpoint innerhalb der while Schleife setze, bleibt der Debugger nur dann stehen, wenn ich Devices hinzugefüge. Zitieren
photron Geschrieben May 8, 2012 at 11:08 Geschrieben May 8, 2012 at 11:08 Beide Threads laufen durch. RecvLoopFlag ist normalerweise True und wird beim destroy auf False gesetzt, damit man die Threads sauber abbrechen kann. Also steht da im Normalbetrieb ein while(True). Dass du im Debugger da nur was passieren siehst wenn du Devices ansteckst ist erwartet. Beim Anstecken schickt dir brickd eine Enumerate Message. Der socketStream.Read() Aufruf blockiert bis Daten zu lesen sind. Also steht der Thread die meiste Zeit in der Read() Methode wenn keine Daten übertragen werden. Zitieren
Nic Geschrieben May 8, 2012 at 11:18 Autor Geschrieben May 8, 2012 at 11:18 Zusammengefasst Thread RecvLoop agiert wie ein Listener bei Änderung des Device-Stacks und der Thread CallbackLoop wie ein Event-Handler bei Device-Rückantworten wie z.b. nach getter-Anfragen (GetCurrentPosition beim Stepper) ? Zitieren
photron Geschrieben May 8, 2012 at 11:47 Geschrieben May 8, 2012 at 11:47 Nein. Der RecvLoop liest alles was auf dem Socket ankommt und ruft damit HandleMessage() auf. HandleMessage() unterscheidet dann verschiedene Messages: - AddDevice Antworten werden ausgewertet und das entsprechende Device aktualisiert mit den Informationen über Name, Stack ID etc. - Callback Antworten werden in die callbackQueue gesteckt - Andere Nachrichten für bekannte Devices werden in deren entsprechenden answerQueues gesteckt Der CallbackLoop nimmt Callback Antworten aus der callbackQueue und ruft die entsprechenden Callback Funktionen auf, falls solch eine vom Benutzer registriert wurde. Getter Aufrufe für Devices warten maximal 2,5 sec bis in ihrer answerQueue etwas angekommen ist. Zitieren
AuronX Geschrieben May 8, 2012 at 12:52 Geschrieben May 8, 2012 at 12:52 Am Ende ist halt ausgeschlossen, dass der Receive-Thread an einer anderen Stelle blockiert als beim Lesen vom Socket. (Memo an mich/TF: was passiert wenn die BlockingQueue voll ist? Geht das?) Woanders blockieren tut die Anwendung immer dann wenn mana uf die Antwort des Stacks wartet, solche Methoden können aber nur in dem Code vorkommen den der Library-User schreibt. Dieser Code wird nur von dessen eigenen Threads ausgeführt und eben vom Callback-Thread. Das ist ja am Ende der Thread der die "Auslieferung" der Callbacks durchführt. Zitieren
Nic Geschrieben May 8, 2012 at 13:09 Autor Geschrieben May 8, 2012 at 13:09 Verstehe ich das richtig, es gibt für das Socket kein OnReceive Event, das ihm sagt, jetzt lese aus ? Der Thread bleibt beim Lesen solange stehen (Endlosschleife), bis das Stream.Read Daten lesen kann und evaluiert ? Ist das also eine asynchrone Kommunikation ? Zitieren
AuronX Geschrieben May 8, 2012 at 14:00 Geschrieben May 8, 2012 at 14:00 Das ist nciht event-basiert sondern basiert auf blockierenden Funktionsrufen. Das heißt sobald du Stream.Read aufrufst blockiert dieser aufruf, das heißt die Ausführung des Threads wird unterbrochen (keine Schleife o.ä.) bis dort Daten anliegen. Sobald Daten vorhanden sind, geht die Ausführung ganz normal weiter. Das ganze ist also Synchron. Zitieren
Nic Geschrieben May 8, 2012 at 14:42 Autor Geschrieben May 8, 2012 at 14:42 Sorry, verstehe nur Bahnhof Ich rufe explizit nicht stream.read auf sondern dies passiert im Thread RecvLoop, innerhalb der while-Schliefe. Der Thread wird instanziert und sofort gestartet, sobald IPConnection erzeugt wurde. Irgendwann rufe ich in der Anwendung AddDevice auf, damit schreibe ich in den SocketStream. Was und wann triggert dann in RecvLoop das im SocketStream gelesen wird ? Solange dieser Thread nicht terminiert oder destroyed wird, bleibt der Thread aktiv und pollt im Stream ob er lesen kann ? Zitieren
AuronX Geschrieben May 8, 2012 at 15:13 Geschrieben May 8, 2012 at 15:13 Also ganz langsam und von vorn... So sieht im wesentlichen die Hauptschleife des Receive-Thread aus: while(RecvLoopFlag) { byte[] data = new byte[8192]; int length = socketStream.Read(data, 0, data.Length); //mache irgendwas mit den gelesenen Daten } Das passiert in einem eigenen Thread. Ich "debugge" jetzt mal: while(RecvLoopFlag) RecvLoopFlag ist true, also gehe ich in den Schleifenrumpf byte[] data = new byte[8192]; ich lege ein byte-array namens data an int length = socketStream.Read(data, 0, data.Length); Hier wirds spannend: Ich lese vom Stream, dabei ist spezifiziert, dass die Methode Read erst dann zurückkehrt (also erst dann gehts weiter), wenn mindestens ein Byte auf dem Stream lesbar ist. Das heißt solange niemand etwas auf den Stream schreibt wird hier kein Code mehr ausgeführt, der Thread schläft. Sobald jemand auf den Socket schreibt bekommt dein Betriebssystem das mit, dieses weckt den Thread, sagt ihm, dass der IO auf den er wartet angekommen ist und der Thread macht genau dort weiter wo er aufgehört hat. Das heißt jetzt kehrt die Methode Read zurück, data ist befüllt und die Menge der gelesenen Bytes wurde zurückgegeben. Ich hoffe jetzt war das einigermaßen klar... ansonsten sollten wir das villt mal ausskypen, weil villt ist der Knoten ja an einer ganz anderen Stelle ^^ Achso zum Lesen: http://msdn.microsoft.com/en-us/library/system.io.stream.read.aspx LG Jan P.S.: Mir ist dabei grad was aufgefallen... gibt nen neuen Thread ^^ Zitieren
Nic Geschrieben May 8, 2012 at 15:35 Autor Geschrieben May 8, 2012 at 15:35 ...dabei ist spezifiziert, dass die Methode Read erst dann zurückkehrt wenn mindestens ein Byte auf dem Stream lesbar ist. Das heißt solange niemand etwas auf den Stream schreibt wird hier kein Code mehr ausgeführt, der Thread schläft. Sobald jemand auf den Socket schreibt bekommt dein Betriebssystem das mit, dieses weckt den Thread, sagt ihm, dass der IO auf den er wartet angekommen ist und der Thread macht genau dort weiter wo er aufgehört hat. Das heißt jetzt kehrt die Methode Read zurück, data ist befüllt und die Menge der gelesenen Bytes wurde zurückgegeben. Genau der Block hätte gereicht. Den Rest und der zynische Unterton gehören hier nicht ins Forum. Es ist durchaus möglich, das man als Anwend.entw. unterscheidet zw. eigener Implm. und der eingeb. Framework-API in der ich i.d.R. nix zu suchen habe. Insofern kann "sobald du Stream.Read aufrufst" ev. zu Irritationen führen. Zitieren
AuronX Geschrieben May 8, 2012 at 16:11 Geschrieben May 8, 2012 at 16:11 Da war kein zynischer Unterton mit dabei, also bleib mal locker... ich hatte nur wirklich keinen Plan was der Teil war den du nicht verstanden hast, also habe ich mich bemüht alles zu erklären. Also ganz friedlich, okay? Und das mit dem Skype war auch ernst gemeint, wollte dich nicht angreifen oO Zitieren
Nic Geschrieben May 8, 2012 at 17:16 Autor Geschrieben May 8, 2012 at 17:16 Also ich bin in Hobby-Sachen immer locker Skype ist nicht vorhanden, also alles andere ist obsolet... Wenn ich mich richtig erinnere gibt es non-blocking mode von Sockets, in diesem Fall würde der Thread am Read nicht warten sondern weiterlaufen ? Zitieren
AuronX Geschrieben May 8, 2012 at 17:41 Geschrieben May 8, 2012 at 17:41 Geben tut es sowas definitiv, aber wenn ich dich richtig verstehe willst du ja auf Delphi arbeiten, da weiß ich nicht was die Standardbibliothek auf welche Weise anbietet. In C# funktioniert das beispielsweise mit dem Stream.ReadTimeout. Bei C# würde dann eine Exception fliegen und du kannst als Entwickler damit umgehen (z.B. erstmal "was anderes machen" und später erneut lesen) Zitieren
Nic Geschrieben May 8, 2012 at 17:57 Autor Geschrieben May 8, 2012 at 17:57 Nein, ich meinte das nicht speziell auf Delphi bezogen, sondern prinzipiell wie das exemplarisch in C# zw. blocking und non-blocking unterschieden wird. C# kann ich eher lesen als Java oder Phyton, darum habe ich das C# Binding analysiert, allerdings waren die Socket-Sachen noch Neuland. Jetzt ist das klarer für die Lsg. in Delphi. Zitieren
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.