![]() |
Event in Thread
Hi,
ich stelle mir grad folgende Frage: Ich könnte ja in einem Thread auch ein Event hinzufügen. Als Beispiel so
Delphi-Quellcode:
wie müsste die procedure DoSendAnMain aussehen?
type
TOnSendAnMain=procedure(Sender: TObject; Irgendwas: string) of object; TMyThread=class(TThread) private FOnSendAnMain: TOnSendAnMain; procedure DoSendAnMain(Irgendwas: string); published property OnSendAnMain: TOnSendAnMain read FOnSendAnMain write FOnSendAnMain; public ... end; So
Delphi-Quellcode:
oder so:
procedure TMyThead.DoSendAnMain(Irgendwas: string);
begin if Assigned(FOnSendAnMain) then FOnSendAnMain(self, Irgendwas); end;
Delphi-Quellcode:
Da sich hinter FOnSendAnMain ja eine Procedure aus einem anderen Thread verbirgt (z.B. Hauptthread) müsste der Zugriff ja Synchron erfolgern, oder sehe ich das falsch, oder ist das hier nicht notwendig?
procedure TMyThead.DoSendAnMain(Irgendwas: string);
begin if Assigned(FOnSendAnMain) then Synchronize(FOnSendAnMain(self, Irgendwas)); end; Gruß Hobbycoder |
AW: Event in Thread
Über Synchronize ist das korrekt. Sofern die Methode nicht im Mainthread definiert ist müsste man statt Synchronize z.B. CriticalSections verwenden.
Die Methode solltest Du wenn möglich über den Constructor übergeben. Andernfalls íst es denkbar, dass es bei einer späteren Zuweisung zu Konflikten kommen kann, wenn eine alte Methode gerade ausgeführt wird während eine neue zugewiesen wird. Dann müsste man die Zugriffe nochmal z.B. über eine CriticalSection absichern. |
AW: Event in Thread
Ich mache das bisher so, dass ich den Thread Suspended starte, dann die Methoden zuweise und mit Resume dann losmarschieren lasse.
Wie würde denn so ein Create und dann die Zuweisung aussehen? Es wird ja nur ein Pointer übergeben. |
AW: Event in Thread
Delphi-Quellcode:
TMyThread=class(TThread)
private fOnSendAnMain: TOnSendAnMain; procedure DoSendAnMain(Irgendwas: string); public constructor Create(aOnSendAnMain: TOnSendAnMain); overload; end; constructor TMyThread.Create(aOnSendAnMain: TOnSendAnMain); begin fOnSendAnMain := aOnSendAnMain; Create(False); end; |
AW: Event in Thread
Ja, klar logisch.
Manchmal denke ich etwas zu kompliziert ;-) |
AW: Event in Thread
Das ist doch Jacke wie Hose.
Will sagen: Du kannst beides problemlos machen. Die Variante mit Synchronize hält den Thread halt mehr auf. Dafür solltest bei dieser Variante:
Delphi-Quellcode:
Dokumentieren, dass das Event in einem separaten Thread aufgerufen wird und eventuelle Interaktionen mit der GUI besonders behandelt werden müssen.
procedure TMyThead.DoSendAnMain(Irgendwas: string);
begin if Assigned(FOnSendAnMain) then FOnSendAnMain(self, Irgendwas); end; Je nachdem wie du das Event auslöst, muss ggf. der Empfängercode anders geschrieben werden. Du hast also die Wahl zwischen Idiotensicher (Synchronize im Thread) oder Performance. Falls das Event ausschließlich für GUI Darstellung genutzt wird, ist es komplett egal, da ist Variante 2 (Synchronize im Thread) vll. intuitiver. |
AW: Event in Thread
Hmm..
Ich würde das wie schon geschrieben über den Contructor lösen:
Delphi-Quellcode:
type
TOnSendAnMain=procedure(Sender: TObject; Irgendwas: string) of object; TMyThread=class(TThread) private FNeedSync : boolean; FIrgendwas: string; FOnSendAnMain: TOnSendAnMain; procedure DoSendAnMain(Irgendwas: string); procedure DoSendAnMainSyc; protected procedure Execute; override; property OnSendAnMain: TOnSendAnMain read FOnSendAnMain write FOnSendAnMain; property NeedSync : boolean read FNeedSync write FNeedSync; public constructor create(AOnSendAnMain: TOnSendAnMain;ANeedSync : boolean);reintroduce; end; implementation { TMyThread } constructor TMyThread.create(AOnSendAnMain: TOnSendAnMain; ANeedSync: boolean); begin FIrgendwas := ''; FOnSendAnMain:= AOnSendAnMain; FNeedSync := ANeedSync; inherited create(false); end; procedure TMyThread.DoSendAnMain(Irgendwas: string); begin FIrgendwas := Irgendwas; if FNeedSync then begin Synchronize(DoSendAnMainSyc); end else DoSendAnMainSyc; end; procedure TMyThread.DoSendAnMainSyc; begin if Assigned(FOnSendAnMain) then FOnSendAnMain(self, FIrgendwas); end; procedure TMyThread.Execute; begin DoSendAnMain('Bla bla bla'); end; Dadurch kann beim erstellen des Thread-Objectes entschieden werden, ob ein Sync notwendig ist, oder nicht... |
AW: Event in Thread
Meiner Erfahrung nach ist es in 99% der Fälle unerwünscht, dass der Thread ein komplettes Event intern schon synchronisiert.
Wenn du das Event einfach nur ganz normal auslöst und dokumentierst, dass es im Kontext eines seperaten Threads aufgerufen wird, hat der Benutzer sehr viel mehr Möglichkeiten für spezifische Optimierungen. Wenn z.b. ClientSocket in einem Thread auf eingehende Daten wartet und dann ein Event zur Verarbeitung auslöst, ist in den meisten Fällen ja gar keine Synchronisierung mit dem Main-Thread erforderlich bzw. nur für ein kurzes GUI Update nach der eigentlichen Verarbeitung. |
AW: Event in Thread
Alternativ diese Synchronisierung per Option (Property) aktivierbar/deaktivierbar.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:12 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz