Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Kommunikation zw. Threads


Peter2002 - Do 19.02.09 23:21
Titel: Kommunikation zw. Threads
Servus,

wie realiesiert man am besten eine Kommunikation zwischen Threads?
Also, einer soll den andernen informieren, dass eine bestimmte Aktion abgeschlossen ist und evtl. ein Ergebnis übergeben.

Besten Dank im Voraus


jaenicke - Do 19.02.09 23:29

Da gibt es viele Möglichkeiten, eine wären Windowsbotschaften, dann gibts da noch Pipes, Semaphore, und einiges mehr.

Windowsbotschaften sollte klar sein, zu Semaphoren und Threads steht hier etwas:
http://edn.embarcadero.com/article/29908


Peter2002 - Fr 20.02.09 18:11

Danke. Werd mir den Link gleich mal ansehen.

Mit Windowsmessages habe ich es auch schon versucht. Aber irgendwie kommen die Messages nicht im Thread an... Kennt jemand ein Beispiel, wie man PostThreadMessage richtig benutzt bzw. die Nachtrichten im Thread dann abruft?


delfiphan - Fr 20.02.09 18:31

Hast du im Thread eine Messageschleife?


BenBE - Sa 21.02.09 14:09

@delfiphan: Da wär glaube ein kurzes Beispiel nicht schlecht.

Ferner wären als Kommunikationsmittel noch Mutexe sowie Lock-Free Data-Structures zu erwähnen.


delfiphan - Sa 21.02.09 17:24

Nimm z.B. eine FIFO Liste und schütze die Zugriffe mit CriticalSections. Wenn du eine Nachricht versenden willst, locke die Liste und füge das Messageobjekt mit den nötigen Infos hinzu. Die andere Seite prüft periodisch, ob sich etwas in der Liste befindet. Zum "Empfangen" der Nachricht Liste locken, Inhalt rausziehen und leeren, und schliesslich wieder unlocken. Danach die Kopie der Liste in Ruhe abarbeiten. Wenn du nicht periodisch prüfen willst, ob was Neues in der Liste ist brauchst du sowas wie Events.

Wenn du einen Thread eventbasiert betreiben [http://www.delphi-library.de/viewtopic.php?p=550543] willst, dann brauchst du eine Messageschleife, die nichts weiteres tut, als zu "schlafen" bis eine neue Nachricht eintrifft. Sobald eine Nachricht eintrifft, wird der Thread wieder aktiv und bearbeitet diese.

Welche Lösung für dich am besten ist, hängt davon ab, was die Threads genau tun, und was für Messages (Zweck) du verschicken willst.

Semaphores und Mutexes sind nur verschiedene Mittel, die verhindern, dass gewisse Stellen im Code von mehr als ein oder mehreren Threads gleichzeitig ausgeführt werden können. Mit Messages rumschicken hat das direkt nichts zu tun.


Peter2002 - Mo 23.02.09 23:11

Klasse! Da hast du dir ja richtig Arbeit gemacht.
Die eventbasierte Variante ist glaube ich der richtige Ansatz für mich...
Das Source-Beispiel muss ich jetzt nur noch verstehen :roll:


dummzeuch - Di 24.02.09 22:03

Zum Thema Kommunikation mittels Messages: Das sollte man nur machen, wenn es nur selten aufgerufen wird. Zu haeufig benutzt erzeugt extrem hohe Prozessorlast und blockiert irgendwann das Programm. Besser man arbeitet mit Events.

Ich hab' das heute gerade erst wieder durchexerziert. Windows-Messages: Das Programm wird elendig langsam und friert irgendwann ein, CPU-Last auf >30% (=ein Kern voll ausgelastet, ein anderer macht ein bisschen was). Umgestellt: CPU-Last kaum sichtbar, Programm funktioniert problemlos.


delfiphan - Di 24.02.09 22:49

Messages machen auch nicht dasselbe wie Events (wenn du denn Delphi-Events meinst). Die müsste man dann synchronisiert (Synchronize/Queue) aufrufen, damit sie ausserhalb des eigenen Threads ausgeführt werden. Synchronize verschickt jedoch auch eine Windows-Message, da sparst du also sicher nichts. Und wenn du nicht synchronisiert, vergleichst du zwei völlig verschiedene Dinge...

Die Alternative wäre das Messaging komplett selbst zu implementieren (ähnlich wie das Beispiel mit FIFO oben, jedoch nicht mit Polling). Vorteil hier ist, dass du das Aussehen der Messages selbst gestalten kann.

Bei meinem Beispiellink oben ging es explizit um die Behandlung von Windows-Messages. Es spricht natürlich nichts dagegen, das ganze selbst effizienter zu implementieren. Mit PostMessage hast du halt alles schon mit dabei, sogar die Kommunikation zwischen verschiedenen Prozessen.


dummzeuch - Mi 25.02.09 08:07

user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
Messages machen auch nicht dasselbe wie Events (wenn du denn Delphi-Events meinst).


Nein, ich meine Windows Event Objekte (CreateEvent() WaitForxxx() usw.) bzw. TEvent aus SyncObjs.

Zitat:

Synchronize verschickt jedoch auch eine Windows-Message, da sparst du also sicher nichts.


Ich kann mich taeuschen, aber ich meine, dass Synchronize in neueren Delphi Versionen nicht mehr mit Messages arbeitet. Ausserdem fuehrt Synchronize lediglich Code im Kontext des Haupt-Threads aus, taugt also recht wenig, wenn man mit anderen Threads kommuniziern will.

Zitat:

Die Alternative wäre das Messaging komplett selbst zu implementieren (ähnlich wie das Beispiel mit FIFO oben, jedoch nicht mit Polling). Vorteil hier ist, dass du das Aussehen der Messages selbst gestalten kann.


Und der Nachteil ist, dass es wie oben beschrieben im Vergleich zu anderen Methoden der Threadkommunikation sehr langsam und CPU-lastig ist. Man sollte es also nur einsetzen, wenn man es selten aufruft.

twm


alzaimar - Mi 25.02.09 09:16

Vielleicht ist ja eine Threadpool-Klasse etwas für Dich? Das ist eine Klasse, die einzelne, zu definierende Jobs im Hintergrund parallel ausführt, d.h. es arbeiten mehrere Threads gleichzeitig.

Hier der Link: http://www.delphipraxis.net/topic111982,0,asc,0.html


delfiphan - Mi 25.02.09 13:00

user profile icondummzeuch: Dann bin ich mit dir völlig einverstanden. Man müsste dann halt alles selbst programmieren, wäre dafür aber schneller.