Update verderop: [rml]Reptile209 in "[ delphi] Data uitwisselen tussen threads"[/rml]
Ik ben een progsel aan het maken dat multi-threaded werkt. Nu loop ik echter constant aan te hikken tegen het uitwisselen van informatie tussen threads.
Even een korte (voorbeeld) situatie:
Er is een main-thread met een form. Op dat form staat een memo, een button en een edit.
Er is een thread die een TCP-connection bijhoudt.
Nu zijn er twee zaken die mogelijk moeten kunnen zijn:
* het form wil data verzenden vanuit de edit na het aanklikken van de button
* binnenkomende data moet teruggegeven worden aan het form om in de memo te worden gezet.
Voor deze laatste uitwisseling (thread -> main) ben ik tot nu toe op een paar verschillende oplossingen gekomen, maar ze kriebelen allemaal een beetje. Even in het kort:
1) Je kan data in een object verpakken dat je maakt in de thread. Een pointer naar dat object stuur je als wparam met een PostMessage() naar de main waar hij wordt afgevangen, verwerkt en vrijgegeven. Probleem daarbij is, dat als de main niks met de message doet (nog niet geimplementeerd, niet interessant, etc), je met een memleak zit wat het object betreft. Is op z'n minst slordig.
2) Je kan direct (via synchronize) vanuit de thread op het memo schrijven. Onzin: dat is lelijk en beperkt je enorm in latere aanpassingen.
3) Je kan een event-systeem gebruiken:
(even in het kort en uit mijn hoofd, maar het idee staat er wel)
Hier zit ik met de twijfel of dit "automagisch" thread-safe is, en of het dus altijd goed gaat.
Wat is nou een goede, nette en betrouwbare methode om dit soort dingen te doen? Waar moet ik op letten?
Ik kom (vooral in combinatie met synchronize) nogal eens op rare fouten en deadlocks uit: roep vanuit een main functie een thread-functie aan, die vervolgens ergens een synchronize gebruikt: einde verhaal...
Google en de search leveren steeds een heleboel "net niet" verhalen op. Alleen vage verwijzingen naar semaphores, gebruik messages (ja, maar die datastructuur dan), gebruik events (implementatie?), etc.
Iemand ergens wat tips, een gestructureerde tutorial met uitgewerkt voorbeeld, of andere nuttige info?
Ik ben een progsel aan het maken dat multi-threaded werkt. Nu loop ik echter constant aan te hikken tegen het uitwisselen van informatie tussen threads.
Even een korte (voorbeeld) situatie:
Er is een main-thread met een form. Op dat form staat een memo, een button en een edit.
Er is een thread die een TCP-connection bijhoudt.
Nu zijn er twee zaken die mogelijk moeten kunnen zijn:
* het form wil data verzenden vanuit de edit na het aanklikken van de button
* binnenkomende data moet teruggegeven worden aan het form om in de memo te worden gezet.
Voor deze laatste uitwisseling (thread -> main) ben ik tot nu toe op een paar verschillende oplossingen gekomen, maar ze kriebelen allemaal een beetje. Even in het kort:
1) Je kan data in een object verpakken dat je maakt in de thread. Een pointer naar dat object stuur je als wparam met een PostMessage() naar de main waar hij wordt afgevangen, verwerkt en vrijgegeven. Probleem daarbij is, dat als de main niks met de message doet (nog niet geimplementeerd, niet interessant, etc), je met een memleak zit wat het object betreft. Is op z'n minst slordig.
2) Je kan direct (via synchronize) vanuit de thread op het memo schrijven. Onzin: dat is lelijk en beperkt je enorm in latere aanpassingen.
3) Je kan een event-systeem gebruiken:
(even in het kort en uit mijn hoofd, maar het idee staat er wel)
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| type TMyDataRead = procedure(Sender: TObject; const ReadStr: string; const ReadInt: integer) of Object type TMyDataThread(TThread) private FOnDataRead: TMyDataRead procedure DoDataRead; ... published property OnDataRead: TMyDataRead read FOnDataRead write FOnDataWrite; ... end; ... procedure TMyDataRead.Execute; begin ... while not Terminated do begin ... if NieuweDataBeschikbaar then DoDataRead; ... end; procedure TMyDataThread.DoDataRead; begin if assigned(FOnDataRead) then FOnDataRead(self, 'Dit is een Test!', 16); // Hier zou je dus normaal "echte" data hebben... :P end; ... procedure Form1.OnCreate; begin MyDataRead := TMyDataRead.Create(true); MyDataRead.OnDataRead := OnDataRead; MyDataRead.FreeOnTerminate := true; MyDataRead.Resume; end; procedure Form1.OnDataRead(Sender: TObject; const ReadStr: string; const ReadInt: integer); begin Memo1.Lines.Add(ReadStr); end; |
Hier zit ik met de twijfel of dit "automagisch" thread-safe is, en of het dus altijd goed gaat.
Wat is nou een goede, nette en betrouwbare methode om dit soort dingen te doen? Waar moet ik op letten?
Ik kom (vooral in combinatie met synchronize) nogal eens op rare fouten en deadlocks uit: roep vanuit een main functie een thread-functie aan, die vervolgens ergens een synchronize gebruikt: einde verhaal...
Google en de search leveren steeds een heleboel "net niet" verhalen op. Alleen vage verwijzingen naar semaphores, gebruik messages (ja, maar die datastructuur dan), gebruik events (implementatie?), etc.
Iemand ergens wat tips, een gestructureerde tutorial met uitgewerkt voorbeeld, of andere nuttige info?
[ Voor 5% gewijzigd door Reptile209 op 11-05-2003 15:38 ]
Zo scherp als een voetbal!