Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Synchronisierung von Subthreads (VCL) + Pointerzugriff (https://www.delphipraxis.net/67972-synchronisierung-von-subthreads-vcl-pointerzugriff.html)

markusj 22. Apr 2006 16:24


Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Hallo Leuts,

ich hab mal eine kleine Frage:

Ich habe einen VCL-Thread dem ich (als Beispiel) einen Zeiger auf einen Boolan-Wert übergeben habe.
So, nun einige Frage (insbesonderen an den Thread-Experten v.D. Luckie *g*):

Kann ich einfach auf diesen Boolean-Wert aus dem Thread zugreifen?
Wenn nein, wie kann ich das ganze Synchronisieren? Ich weis wie ich normale Prozeduren und Funktionen untereinander Synchronisiere, aber hier müsste ja eine Thread-Interne Prozedur Synchronisiert werden ... oder geht das genauso mit Synchronize???

EDIT: Und wenn wir schon dabei sind ... wie sieht das ganze mit einem TMemoryStream aus? Auf diesen wird allerdings !garantiert! nicht vom Hauptthread zugegriffen! (wird von mir gelockt)

Aber das wars noch nicht, ich habe noch einen weitere Frage ... Wie kann ich zwei Nebenthreads miteinander Synchronisieren, ohne über den Hauptthread zu gehen? Diese beiden Thread sollen nämlich miteinander kommunizieren.

mfG

Markus

xaromz 22. Apr 2006 16:54

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Hallo,

eine Möglichkeit wären CriticalSections. Such mal in der Hilfe nach Delphi-Referenz durchsuchenEnterCriticalSection.

Gruß
xaromz

markusj 22. Apr 2006 16:59

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Für was? Den Variablenzugriff, den Threadzugriff oder beides ... ach ja, ich wusste gar nicht, dass das auch bei VCL geht^^.

mfG

Markus

xaromz 22. Apr 2006 17:08

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Hallo,
Zitat:

Zitat von markusj
Für was? Den Variablenzugriff, den Threadzugriff oder beides

Für alles natürlich. Ein Thread läuft von EnterCriticalSection durch bis LeaveCriticalSection, ohne dass ein anderer Thread dazwischenfunken kann.
// Anmerkung: Deshalb sollten diese Befehle auch sehr sparsam verwendet werden und der Code dazwischen kurz und effizient sein.
Zitat:

Zitat von markusj
ach ja, ich wusste gar nicht, dass das auch bei VCL geht^^.

Die Methode TThread.Synchronize benutzt nichts anderes als Enter-/LeaveCriticalSection. Was soll die VCL auch sonst verwenden wenn nicht das Windows-API?

Gruß
xaromz

Basilikum 22. Apr 2006 17:45

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Zitat:

Zitat von xaromz
Die Methode TThread.Synchronize benutzt nichts anderes als Enter-/LeaveCriticalSection. Was soll die VCL auch sonst verwenden wenn nicht das Windows-API?

das stimmt so nicht ganz: Synchronize platziert in der Message-Queue eine Nachricht, der Hauptthread möge doch bitte im Rahmen des Message-Processing die übergebene Callback-Funktion aufrufen... so wird sichergestellt, dass die Funktion synchron zum (dh. vom) Hauptthread ausgeführt wird

markusj 22. Apr 2006 17:48

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
So, noch eine Frage: Wie sieht die sache aus, wenn ich 100% sicherstellen kann,dass kein Zugriff auf die Eigenschaft erfolgt?
Kann ich dann darauf verzichten?
Das Problem ist ganz einfach, dass ich einen TMemoryStream in eine Klasse im Hauptthread habe, die u.a. diesen Stream verwaltet.
Eine leistungsintensive Aufgabe habe ich in einem seperaten Thread ... und dieser soll auf den MemoryStream zugreifen.
Kann ich in dem Fall auf TCriticalSections verzichten? Die Klasse blockiert jeden Zugriff auf den Stream (von Auserhalb) während der Threadlaufzeit.

mfG

Markus

xaromz 22. Apr 2006 17:57

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Hallo,
Zitat:

Zitat von Basilikum
das stimmt so nicht ganz: Synchronize platziert in der Message-Queue eine Nachricht, der Hauptthread möge doch bitte im Rahmen des Message-Processing die übergebene Callback-Funktion aufrufen... so wird sichergestellt, dass die Funktion synchron zum (dh. vom) Hauptthread ausgeführt wird

Weiß ich doch :wink: ; ich wollte nur darauf hinweisen, dass die VCL für Synchronisation auch CriticalSections verwendet. Was Synchronize innerhalb der Section macht, ist ja nebensächlich.
Zitat:

Zitat von markusj
Das Problem ist ganz einfach, dass ich einen TMemoryStream in eine Klasse im Hauptthread habe, die u.a. diesen Stream verwaltet.
Eine leistungsintensive Aufgabe habe ich in einem seperaten Thread ... und dieser soll auf den MemoryStream zugreifen.
Kann ich in dem Fall auf TCriticalSections verzichten? DIe Klasse blockiert jeden zugriff auf den Stream während der Theradlaufzeit.

Wenn Du hundertprozentig sicher bist, dass kein gleichzeitiger Zugriff stattfindet, dann kannst Du auch darauf verzichten. Du solltest aber bedenken, dass dann eine Änderung am Programmdesign evtl. große Auswirkungen haben kann (man vergisst sowas nämlich auch schnell wieder). Du solltest unbedingt dokumentieren, wass Du da machst.
Besser ist es immer, sich abzusichern. Und Fehler zu debuggen, die auf solche Konstrukte zurückzuführen sind, wünsch' ich meinem ärgsten Feind nicht :zwinker: .

Gruß
xaromz

markusj 22. Apr 2006 18:11

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
OK, das gehört zum Klassendesign, dass immer nur eine Aufgabe ausgeführt wird, solange wird ein Lock gesetzt, damit nicht verändert wird.

So noch eine wichtige Frage: Wie sieht das ganze bei einer Synchronisierung von zwei Subthreads untereinander aus? Muss das TCriticalSections dort auch als globale Variable vereinbart sein? Oder reicht es, wenn es in der Thread-Klasse des Kind-Threades als public vereinbart wird und somit dem Mama-Thread zu verfügung steht?

Eine kurze Struktur meiner Idee:

Hautpthread
||
Mama-Thread mit uses ClassKind-Thread
|
Kind-Thread mit TCriticalSections als Public

Funktioniert das?

mfG

Markus

markusj 23. Apr 2006 10:25

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
So, noch eine Frage (nach der obigen, die noch nicht beantwortet ist):

Wie sieht die Sache umgekehrt aus? Wie greift der Hauptthread auf den Nebenthread zu?
Critical Sections? Hat der Hauptthread auch ein Synchronize, oder muss ich hier zu Fuß Synchronisieren?

mfG

Markus

alzaimar 23. Apr 2006 10:45

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Gemeinsam verwendete Resourcen/Variablen etc. sollten für den Zugriff grundsätzlich gekapselt werden, so etwa:
Delphi-Quellcode:
Procedure ThreadsafeSetValue (aMyValue : TSomeType);
Begin
  myCS.Enter;
  Try
    fValue := aMyValue; // Na ja, fValue.Assign bei Objekten
  Finally
    myCS.Leave;
  End
End;

Procedure ThreadsafeGetValue (Var aMyValue : TSomeType);
Begin
  myCS.Enter;
  Try
    aMyValue := fValue;
  Finally
    myCS.Leave;
  End
End;
Wenn Du das als Get/Set-Methoden einer Eigenschaft implementierst, ist der Zugriff darauf sicher. Zum Verständnis: Eine Critical Section hält nicht etwa alle anderen Threads an, sondern sorgt dafür, das ein zweiter Aufruf von myCS.Enter so lange wartet, bis der erste Aufrufer myCS.Leave aufgerufen hat. Der erste Aufruf von myCS.Enter schließt sozusagen eine Tür von *innen*. myCS.Leave öffnet sie wieder.

markusj 23. Apr 2006 10:50

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Das bedeutet, dass ich wieder ein TCriticalSections als Globale Variable brauche?
Und wenn ich zwei Subthreads aufeinander Zugreifen lasse? Brauche ich dann auch ein globales Critical Section? Oder reicht es, wenn ich es bei einem Thread als public deklariere und dessen Unit per Uses einbinde?

mfG

Markus

HERMES 23. Apr 2006 11:56

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Es ist egal wie du es machst, aber die Threads müssen das selbe CriticalSection Objelt benutzen, damit eine Synchronisation stattfindet.

alzaimar 23. Apr 2006 12:14

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Du musst Dir überlegen, in wessen Kontext die Variable lebt.
Wenn z.B. Thread1 irgendetwas deklariert, verwendet oder kontrolliert, dann packst Du die Eigenschaft in Thread1:
Delphi-Quellcode:
Type
  TMyThread = Class (TThread)
  Private
    fMyCS : TCriticalSection;
  Public
    Property MyValue : TSomeType Read GetValue Write SetValue;
  End;
...
Oder du deklarierst Dir eine eigene Klasse, die den threadsicheren Zugriff implementiert. Das würde ich empfehlen, wenn die Eigentusverhältnisse nicht eindeutig geklärt sind. Alles eine Frage der Sichtweise: Die Implementierung ist in jedem Fall ähnlich. :stupid:

markusj 23. Apr 2006 15:12

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Vielen Dank,

ich denke, ich werd das Objekt in den Unter-Unter-Thread Packen, welcher bei den beiden anderen über uses eingebunden ist
--> Zugriff auf das public-Objekt var csMan : TCriticalSection sollte möglich sein ... wenn nicht, bitte warnen *g*

mfG

Markus

markusj 23. Apr 2006 16:51

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
So, mir ist gerade noch eine ganz neue Idee gekommen ...
Ist es möglich, eine ganz normale Klasse einfach zu einenm Thread umzumodden?
Kann ich dann auf dessen Methoden zugreifen, und wenn ja, werden die dann im Hauptthread oder im Subthread ausgeführt?
BTW: Was passiert nach dem Execute? Ich meine, wenn der Code abgearbeitet ist, und kein FreeOnTerminate aktiviert ist? Ist der Thread dann Suspended? In welchem Zusand befindet er sich dann?

mfG

Markus

markusj 24. Apr 2006 13:57

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
*push*

himitsu 24. Apr 2006 15:40

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Wenn du nur auf einen 1-, 2-, oder 4-Byte-Wert zugreifen willst, dann sollte es keine Probleme geben, wenn diese zur selben Zeit ausgelesen werden, nur beim ändern mußt du aufpassen, aber eventuell hilft da auch schon ein kurzer Umschalter in den SingelThreadModus.

Var B: ByteBool;

auslesen wie immer
z.B.
Delphi-Quellcode:
If B Then ...
Und das Setzen
Delphi-Quellcode:
//B := True;
ASM
  LOCK MOV &B, $FF
End;

//B := False;
ASM
  LOCK MOV &B, 0
End;

markusj 24. Apr 2006 16:01

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Könntest du mir kurz erklären, was dieser Code macht/bedeutet? Ich kann leider (noch) kein ASM ...
Ach ja, die anderen Fragen in den Posts 14 und 15 "dürfen" auch beantwortet werden *g*

ansonsten, Danke!

mfG

Markus

himitsu 24. Apr 2006 17:14

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Im Grunde sind es jeweils 2 Befehle.

Dieses kopiert den Wert/Inhalt von x2 nach x1
Code:
MOV x1, x2
Hier also den Wert $FF in den Speicherbereich der Variable B.
Code:
MOV &B, $FF
Wobei das obere nur die Kurzfassung ist, ausfühlich würde es so aussehn, wobei B eigentlich ein Pointer (hier ist es ein BYTEPoinTeR) zu einem bestimmten Speicherbereich ist:
Code:
MOV BYTE PTR &B, $FF
MOV BYTE PTR [Pointer], $FF
Das LOCK ist ein Befehl, welcher die CPU für den nachfolgenden Befehl in einen Singlethreadmodus schaltet, es wird also sozusagen nur der nachfolgende Befehlausgeführt, während die anderen threads warten ... somit kann also kein anderer Thread wärend dieser Zeit Befehl ausführen, welcher zu dieser Zeit eventuell auch auf deisen Speicherbereich zugreifen könnte (es läuft ja schließlich Keiner)

also
Delphi-Quellcode:
LOCK  MOV  BYTE PTR &B, $FF
oder
Delphi-Quellcode:
LOCK  MOV  &B, $FF
setzt alle Bits (ist beim ByteBounter halt besser) auf 1 und somit auf TRUE, ohne daß zur selben Zeit ein anderer Thread auf B zugreifen kann.
Darum kann man auch ganz normal lesend auf B zugreifen, ohne das es Probleme gibt.

markusj 24. Apr 2006 17:40

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Danke!

EDIT:

Zitat:

Zitat von markusj
So, mir ist gerade noch eine ganz neue Idee gekommen ...
Ist es möglich, eine ganz normale Klasse einfach zu einenm Thread umzumodden?
Kann ich dann auf dessen Methoden zugreifen, und wenn ja, werden die dann im Hauptthread oder im Subthread ausgeführt?
BTW: Was passiert nach dem Execute? Ich meine, wenn der Code abgearbeitet ist, und kein FreeOnTerminate aktiviert ist? Ist der Thread dann Suspended? In welchem Zusand befindet er sich dann?

mfG

Markus

Wie siehts damit aus?

Delphi-Freak 28. Apr 2006 17:15

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Das würde mich auch interessieren, wollte gerade einen Beitrag dazu schreiben...
also *PUSH*

LG, ich

himitsu 28. Apr 2006 18:36

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Wenn du den Schreib-/Lesezugriff innerhalb einer Klasse gegenseitig vor gemeinsamen Zugriff irgendwie (gibt ja mehrere Möglichkeiten) (b)locks, dann kannst du sie auch ohne Probleme von mehreren Thread aus ansprechen.

Delphi-Freak 28. Apr 2006 18:39

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
War das die Antwort auf das hier, dann steh ich nämlich auf der Leitung...
Zitat:

Zitat von markusj
Ist es möglich, eine ganz normale Klasse einfach zu einenm Thread umzumodden?

LG, ich

himitsu 28. Apr 2006 18:44

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
upps, da hab'sch wohl was falsch verstanden (also keine klasse für threads ummodden)

aber zu deiner Frage sollte es doch was geben ... ist in Delphi nicht schon 'ne Thread-Klasse drin?

Delphi-Freak 28. Apr 2006 18:48

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Nein, ich meine man hat irgendeine mehr oder weniger komplexe Klasse, die manchmal etwas länger braucht. Damit das Programm dabei nicht einfriert, und man z. B. den Vorgang abbrechen kann, wäre es gut, das ganze in einen Thread zu verpacken. Das war die Frage - zumindest so wie ich sie verstanden und dann auch "weitergefragt" hab...

LG, ich

Frickeldrecktuxer_TM 28. Apr 2006 19:15

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Zitat:

Zitat von Delphi-Freak
Nein, ich meine man hat irgendeine mehr oder weniger komplexe Klasse, die manchmal etwas länger braucht.

Seit wann geht das denn?!
Eine Klasse braucht nicht lange, ein Task braucht lange. Eine Klasse in einen Thread auslagern zu wollen zeugt davon, irgendwas noch nicht vollständig verstanden zu haben.
Nur mal angenommen mit jeder Methode, die aufgerufen wird, wird ein Kindthread abgespalten und die Methode dort ausgeführt. Der Methodenaufruf würde dann sofort zurückkehren. Und wann zerstörst du das Objekt? Nachdem der Call zurückkehrt? Damit reißt du dem Thread das Objekt, auf das er arbeitet, unter den Füßen weg. Wartest du auf das Beenden des Threads? Dann hast du auch nichts gewonnen, weil du blockierend wartest oder mit ProcessMessages() periodisch die Nachrichtenschleife abarbeitest, und das kannst du auch direkt im Task machen. Gar nicht? Dein Anwender wird es dir danken.
Thread-Modelle und Klassenmodelle beißen sich prinzipbedingt. Das leuchtet ein, wenn man beispielsweise Äpfel mit Birnen vergleicht. Ein Thread ist ein Scheduler-Element, das die zeitliche Verarbeitung von Code regelt. Eine Klasse ist ein logisches, vollständig abstraktes Element, das Daten und Code beinhalten kann, und zwar Code mit mehreren Einsprungpunkten (viele Methoden). Es ergibt wenig Sinn, eine abstrakte Informationsgliederung in eine zeitliche Regelung zu packen, es würde ja ohnehin nichts passieren.
Das Problem, vor dem du stehst, ist nicht, daß deine "Klasse lange braucht", sondern daß dein Task lange braucht. Die Lösung des Problems hast du in eine Klasse gekapselt, aber die Klasse alleine führt noch nicht den Task aus. Also mach es richtig und lagere den Task in einen Thread aus, und nicht die Lösung des Problemes. Starte einen Thread und führe in ihm den Code aus, der das Objekt instanziert, initialisiert, den Task erledigt und wieder ordentlich aufräumt. Am Ende kannst du eine Message an den Hauptthread schicken, um in dessen Kontext den Anwender über das Ergebnis des Tasks zu benachrichtigen.

Zitat:

Zitat von markusj
Kann ich dann auf dessen Methoden zugreifen, und wenn ja, werden die dann im Hauptthread oder im Subthread ausgeführt?

Code wird in dem Kontext ausfgeführt, in dem er aufgerufen wird. Wenn du in Thread A eine Methode eines Objektes aufrufst, wird diese Methode auch in Thread A ausgeführt.

Delphi-Freak 28. Apr 2006 20:33

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Ja, das ist mir (zumindest nach dem Lesen :mrgreen: ) schon klar, es geht im Konkreten um eine von IdFTP abgeleitete Komponente. Nachdem ja das Verbindungs-Aufbauen etc. länger braucht und dann das Formular einfriert, möchte ich alle Kommunikation mit dem Server in einem eigenen Thread machen. Jetzt gibt es die eine Möglichkeit, in einer von TThread abgeleiteten Klasse alle wichtigen Funktionen (Connect, aber auch Put, Get etc.) nochmals zu deklarieren und dort dann die Parameter in Feldern zwischenspeichern und dann eine Variable auf 'connect' oder einen bestimmten Index setzen, die die Execute-Prozedur in einer while-Schleife immer wieder abfragt und demnach dann die Connect-Funktion der IdFTP-Klasse aufruft.
Gibt es da dann eine bessere Methode? :roll:

LG, ich

Frickeldrecktuxer_TM 28. Apr 2006 20:49

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Zitat:

Zitat von Delphi-Freak
Gibt es da dann eine bessere Methode? :roll:

Als dieses Polling? Aba sischa.
Den Thread starten und ihm eine Message-Loop verpassen. GetMessage() ist synchron und blocking, also vergeudest du damit nichtmal Ressourcen, selbst wenn es auf den ersten Blick nach Polling aussieht. Für ein Beispiel brauchst du dir nur ein beliebiges nonVCL-Programm anzuschauen. Dem Thread postest du mit PostThreadMessage() deine Messages, und dieser arbeitet sie ab. Die Message-Queues arbeiten in-order, das heißt du ganz erstmal eine Connect- und eine Get-Message abschicken, die Get-Message wird bearbeitet, sobald das Connect fertig ist. Der Thread reagiert also auf jede Nachricht, die er bekommt, dein Hauptthread läuft aber weiter. Damit die Oberfläche etwas davon mitgekommt, was der Thread gerade tut, kann der Thread ebenfalls Nachrichten an deinen Haupt-Thread (oder besser: irgendein Fenster, dann hast du Unterstützung durch Delphis message-Schlüsselwort), in denen er mitteilt, daß gerade die Verbindung etabliert wurde oder daß er gerade x Bytes empfangen hat und sie dort und dort hinterlegt sind, damit der Thread die empfangenen Daten entgegennehmen kann.
Kurzum: Alles, was du bei normaler IPC anwendest, kannst du auch bei prozessinternen Threads anwenden, oft ist es nicht verkehrt.

Delphi-Freak 28. Apr 2006 21:09

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Aha! Aber gibt es auch was einfacheres, außer jetzt alle Methoden nochmals zu implementieren? Also dass man das gleich für alle Methoden einer Klasse macht? Anscheinend nicht - oder doch :coder2:

LG, ich

Edit: Oder gibt es wenigstens eine Möglichkeit, einen Pointer auf die Methode und einen Pointer auf alle Parameter zu speichern und die Methode mit Parametern nachher so aufzurufen?

markusj 28. Apr 2006 21:18

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
@Frickeldrecktuxer_TM ... ich habe die Thread-Materie sehr wohl verstanden.
Und ich habe mir gedanken gemacht, bevor ich diese Frage stellte ...
in meinem Programmkontext macht das Auslagern ganzer Klassen Sinn, damit der Benutzer mit anderen Programmteilen arbeiten kann, während sich meine Thread-Klassen-Hybrid selbst verwaltet und nach der Ausführung auf die nächste Aufgabe wartet ...
Ich habe meinen Grund für diese Idee ... aber danke für die Antworten (und an Gerhard Pfister danke fürs Pushen, ich hatte den Thread schon beerdigt ...)

mfG

Markus

*einbisschensauer*

EDIT: @Gerhard ... vielleicht kapselst du den Thread in ein Objekt, welches den Statues des Threads kontrolliert und bei Bedarf an das Hauptprogramm weiterleitet ... als eine Art Dolmetscher ... oder Vermittler

Frickeldrecktuxer_TM 28. Apr 2006 21:27

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Zitat:

Zitat von Delphi-Freak
Aha! Aber gibt es auch was einfacheres, außer jetzt alle Methoden nochmals zu implementieren? Also dass man das gleich für alle Methoden einer Klasse macht? Anscheinend nicht - oder doch :coder2:

Wer hat denn was von Reimplementieren gesagt? :zwinker:

Schnell zusammengetippt und daher mit 100%iger Wahrscheinlichkeit die falschen Bezeichner, aber die kannst du ja in der Online-Hilfe nachschlagen, sieh mir nach, daß ich als Gelegenheits-mit-Delphi-Entwickler nicht alle Klassen der VCL auswendig kenne ;-)
Delphi-Quellcode:
type
  TSomeThread = class(TThread)
    // ...
    private
      FIDIrgendwas: TIDIrgendwas;
  end;

constructor TSomeThread.Create(...);
begin
  inherited;
  FIDIrgendwas := TIDIrgendwas.Create;
end;

procedure TSomeThread.MessageHandler(Message: TMessage); // oder so
begin
  case Message.MsgType of // oder so
    STM_CONNECT
    begin
      FIDIrgendwas.Connect(...);
      // fertig, schicke eine Benachrichtigung an den Hauptthread
    end;

    STM_GET
    begin
      FIDIrgendwas.Get(...);
      // fertig, schicke eine Benachrichtigung an den Hauptthread
    end;
  end;
end;

procedure TSomeThread.Execute(...);
begin
  // Nachrichtenschleife
end;
Und damit die Handler wissen, was zu tun ist, solltest du die die beiden Datenfelder einer Message anschauen. Das sind zwar nur zwei LongWords, aber du kannst einen Pointer zu einem Integer casten, deswegen kannst du beliebig viele Informationen übergeben, indem du einfach einen Record deklarierst, die Daten dort reinpackst und einen Pointer auf den Record an die Nachricht hängst. Casten ist zwar weder schön noch hübsch, aber bei einer C-API, wie Windows nunmal eine hat, leider nicht immer zu vermeiden.

Delphi-Freak 28. Apr 2006 21:42

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Gut, danke!
Und was gehört dann in die Execute-Methode hinein? Ich habe das mal aus einem nonVCL-Proggy herausgekramt, leider aber nicht von mir selber geschrieben :mrgreen:
Delphi-Quellcode:
var
Msg: TMsg;
begin
while GetMessage(Msg, 0, 0, 0) do begin
   TranslateMessage(Msg);
   DispatchMessage(Msg);
end;
Übrigens in der Hilfe zu PostThreadMessage steht folgendes:
Zitat:

Zitat von OH
The system only does marshalling for system messages (those in the range 0 to WM_USER). To send other messages (those above WM_USER) to another process, you must do custom marshalling.

Verstehe ich das falsch, dass man keine Message über WM_USER verwenden kann?

LG, ich

Edit: Tippfehler

Frickeldrecktuxer_TM 28. Apr 2006 21:48

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Zitat:

Zitat von markusj
in meinem Programmkontext macht das Auslagern ganzer Klassen Sinn, damit der Benutzer mit anderen Programmteilen arbeiten kann, während sich meine Thread-Klassen-Hybrid selbst verwaltet und nach der Ausführung auf die nächste Aufgabe wartet ...

Wenn die Klasse selbstverwaltend ist, hast du doch deinen Task, den du in einem Thread ausführen kannst. Wenn die Klasse ein eigenständiger Service ist, kannst du das Verfahren anwenden, daß ich für Delphi-Freak eben beschrieben habe. Das Problem mit einem Kapseln von Threads in eine Klasse ist immer, das dadurch sämtliche Aufrufe asynchron werden und man je nach Bearbeitungsgeschwindigkeit des Aufrufs und des Aufrufers mitunter Probleme kriegt, wenn irgendwer auf Ergebnisse eines anderen angewiesen ist sogar Race-Conditions.
Eine Klasse, bei der jeder Methodenaufruf einen weiteren Thread abspaltet funktioniert einfach nicht ohne weiteres. Was aber geht, ist, durch *manuelle* Synchronisierung lediglich *einen* Thread zu verwenden. Das ist das, was ich eben geschildert habe. Das erfordert allerdings entsprechenden Aufwand, um ein Interface aufzubauen. Und man benötigt immer noch zusätzlichen Kontrollcode. Man lagert also nicht die Klasse (oder den Code der Klasse) in einen Thread aus, sondern man lagert die *Benutzung* in einen Thread aus. Diese Benutzung hat man vorher bereits in seinem einzelnen Haupt-Thread, man lagert also effektiv Code aus diesem Haupt-Thread aus, und lässt nicht einfach Aufrufe in einen Thread münden.
Nimm zum Beispiel einen Code, der aus einem UCS-16LE-Text einen UCS-16BE-Text (16bit pro Zeichen, Little Endianness gegen Big Endianness) macht. Man kann einen TFile-Stream nehmen und, 2 Bytes einlesen, die Reihenfolge tauschen und die 2 Bytes zurückschreiben. Das Lesen und Schreiben, das wahrscheinlich am längsten dauert (falls nicht, macht man's mit 'nem Diskettenlaufwerk, dann dauert's lange :mrgreen:), in asynchronen Aufrufen zu machen, indem man TFileStream entsprechend modifiziert, würde wahrscheinlich schnell sehr viele Threads erzeugen, die alle noch dabei sind, ihre 2 Bytes zu schreiben. Das Resultat wären jede Menge konkurrierende Laufwerkszugriffe, das kann niemand wollen. Stattdessen lagere ich die Benutzung von TFileStream in einen Thread aus, also den gesamten Vorgang: Lesen, Vertauschen, Schreiben. Dadurch sind alle Operationen in "richtiger" Reihenfolge. Aber ich habe nicht die Klasse ausgelagert, sondern die Benutzung.

Zitat:

Zitat von markusj
*einbisschensauer*

War wirklich nicht böse gemeint, aber Klassen und Threads beißen sich nunmal heftig.

Frickeldrecktuxer_TM 28. Apr 2006 22:00

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Zitat:

Zitat von Delphi-Freak
Gut, danke!
Und was gehört dann in die Execute-Methode hinein? Ich habe das mal aus einem nonVCL-Proggy herausgekramt, leider aber nicht von mir selber geschrieben :mrgreen:
Delphi-Quellcode:
var
Msg: TMsg;
begin
while GetMessage(Msg, 0, 0, 0) do begin
   TranslateMessage(Msg);
   DispatchMessage(Msg);
end;

Kein TranslateMessage() und kein DispatchMEssage(). Du hast kein Fenster, also kann DispatchMessage() auch keine WndProc aufrufen. Einfach zwischen dem begin und dem end den Handler aufrufen, oder direkt dort mit case die NAchricht verarbeiten.

Zitat:

Zitat von Delphi-Freak
Übrigens in der Hilfe zu PostThreadMessage steht folgendes:
Zitat:

Zitat von OH
The system only does marshalling for system messages (those in the range 0 to WM_USER). To send other messages (those above WM_USER) to another process, you must do custom marshalling.

Verstehe ich das falsch, dass man keine Message über WM_USER verwenden kann?

Das sollte eigentlich nur für Nachrichten über Prozess-Grenzen hinweg gelten, wenn ich mich richtig erinnere.

Delphi-Freak 28. Apr 2006 22:04

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Gut, Danke! :thumb:
Dann sind meine Fragen so weit geklärt...

LG, ich

markusj 29. Apr 2006 08:44

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Ich danke auch ... ich habe aber ein etwas anderes Anwendungsgebiet als Indy

mfG

Markus

PS: So wie du (Frickeldrecktuxer_TM)mir das vorgschlagen hast, hatte ich das auch umgesetzt ... mir ist der Umbau nur praktischer vorgekommen ... hat aer auch Nachteile.

Frickeldrecktuxer_TM 29. Apr 2006 10:00

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Zitat:

Zitat von Frickeldrecktuxer_TM
Zitat:

Zitat von Delphi-Freak
Übrigens in der Hilfe zu PostThreadMessage steht folgendes:
Zitat:

Zitat von OH
To send other messages (those above WM_USER) to another process...


Das sollte eigentlich nur für Nachrichten über Prozess-Grenzen hinweg gelten, wenn ich mich richtig erinnere.

War schon spät gestern, hat nix mit meiner Erinnerung zu tun, steht sogar da :mrgreen:

Delphi-Freak 29. Apr 2006 20:18

Re: Synchronisierung von Subthreads (VCL) + Pointerzugriff
 
Achja, das habe ich übersehen, aber jetzt ist es klar...
Auch wenn es noch immer nicht ganz funktioniert (gibt noch eine AV)... aber das werde ich mir etwas später anschauen; habe gerade meinen Rechner frisch neu aufgesetzt (der Beitrag kommt schon vom neuen System :mrgreen: ). Wahrscheinlich habe ich irgendwo einen Denkfehler eingebaut...

LG, ich


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:56 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz