![]() |
Events in einem Thread
Hallo zusammen,
es geht darum Events von Komponenten in einem Thread aufzurufen. Also der Thread erstellt sich (beispielsweise) einen Timer in Create und setzt das Event auf eine eigene Prozedur. Hier die wichtigsten Zeilen:
Delphi-Quellcode:
Wie ich natürlich bemerken musste läuft das TimerEvent innerhalb meines Hauptthreads ab und blockiert mein Formular.
type TMeinthread = class(TThread)
private Timer : TTimer; procedure TimerEvent(Sender : TObject); public constructor Create(CreateSuspended : Boolean); override; procedure Execute; override; end; implementation constructor TMeinthread.Create(CreateSuspended : Boolean); begin inherited; Timer:=TTimer.Create(nil); Timer.OnTimer=TimerEvent; end; procedure TMeinthread.Execute; begin while not Terminated do Sleep(100); // irgendwas eben end; procedure TMeinthread.TimerEvent(Sender : TObject); begin Sleep(500); // noch irgendwas end; Was kann ich dagegen tun? Das ganze ist nur Beispielhaft, ich stehe häufiger vor dieser Art von Problem. Grüße! |
Re: Events in einem Thread
Delphi-Quellcode:
procedure TMeinthread.Execute;
var i: Integer; begin i := 0; while not Terminated do begin // irgendwas if i = 5 then begin // noch irgendwas i := 0; end; Sleep(100); Inc(i); end; end; |
Re: Events in einem Thread
Du darfst die Komponenten (hier timer) erst in Execute erstellen. Allerdings brauchst du hier eine
![]() |
Re: Events in einem Thread
Danke,
echt schnelle Antworten hier :) also den Timer in Execute zu erstellen ist kein Problem. Verstehe ich das bei den Messageschleifen richtig dass es um Windowsmessages geht? Generiert der Timer eine bestimmte Message die ich abfangen muss/kann (die WM_TIMER)? Wenn das so ist, was tue ich dann bei eigenen Objekten die nicht unbedingt mit Windowsmessages arbeiten? Edit: @wicht Das hilft mir leider nicht weiter. Der Timer war nur Beispielhaft. |
Re: Events in einem Thread
Ja, der Timer arbeitet mit Windowsmessages (ist ja auch direkt von Windows). Di musst du nicht "abfangen" Die TimerKomponente macht das von ganz allein. Die Frage ist nur, was machst du in der ganzen "Wartezeit" in der Methode Execute. Mit sleep warten funktioniert nicht. Du musst irgendeine "Wartefunktion" verwenden. Derer gibt es ein paar:
Jetzt musst du selber entscheiden, was du da hast, und was du am Ende für eine Funktion nehmen kannst. Achte aber darauf, dass du auch die Methode TThread.Terminate neu schreibst und den Abbruch entsprechend einleitest, |
Re: Events in einem Thread
Klar, das mit dem Neuschreiben von Terminate hab ich verstanden (auch warum :) ).
Aber inwiefern kümmert sich der Timer selbst um die Events?
Delphi-Quellcode:
Das Event kommt an, allerdings muss ich selbst darauf reagieren, oder?
type TMeinthread = class(TThread)
private Timer : TTimer; procedure TimerEvent(Sender : TObject); public procedure Execute; override; procedure Terminate; end; implementation procedure TMeinthread.Execute; var Msg : TMsg; begin Timer:=TTimer.Create(nil); Timer.OnTimer:=TimerEvent; while GetMessage(Msg, 0, 0, 0) do begin // Was nun? // case Msg of // WM_TIMER: TimerEvent(Timer); // // end; // ??? end; Timer.Free; end; procedure TMeinthread.TimerEvent(Sender : TObject); begin ShowMessage('Hallo'); // Wird nie ausgeführt ohne die case-Struktur end; procedure TMeinthread.Terminate; begin PostThreadMessage(Self.ThreadID, WM_QUIT, 0, 0); inherited Terminate; end; Also z.B. mit der passenden case-Struktur? Das heißt wenn ich eigene Objekte mit eigenen Events benutze, müsste ich beim Erstellen des Objekts vom Thread die ThreadID übergeben und das Ereigis wird dann druch PostThreadMessage ausgelöst? |
Re: Events in einem Thread
Du kannst natürlich selber mit bspw. case..of auf GetMessage reagieren. Oder du lässt es einfach Windows machen, in dem du DispatchMessage aufrufst. Die TimerKomponente hat sich extra dafür bei Windows "angemeldet".
btw.: In Terminate solltest du besser die beiden Befehle umdrehen. Ist zwar bei dir völlig unerheblich. Aber für zukünftige Projekte. Denn Deine Vorfahrmethode macht nix weiter als die Variable FTerminated auf True zu setzen. Wenn du jetzt folgenden Konstrukt hast:
Delphi-Quellcode:
...könnte es zu einem Laufzeitproblem kommen, wenn du erst WM_Quit setzt und dann FTerminated auf True.
repeat
while GetMEssage(msg,...) do Dispatchmessage(msg); //hier noch etwas anderes tun until terminated; |
Re: Events in einem Thread
Ich glaube, es ist keine gute Idee die TTimer-Komponente in in der Execute-Methode zu erzeugen, denn TTimer ist Teil der VCL und deshalb nicht Thread-safe. Details dazu unter:
![]() |
Re: Events in einem Thread
Wunderbar ich habs verstanden :)
Danke! @samso: Dann funktioniert es aber leider nichtmehr (bzw der falsche Thread führt TimerEvent aus)... Es kommen dann keine Nachrichten bei meinem eigenen Thread an (ich vermute weil der Timer ja von "Hauptthread" erstellt wurde, sich mit dieser ThreadID bei Windows "angemeldet" hat und somit der die Nachrichten erhält). Achja: Für mich ist das Problem gelöst, aber ich beteilige mich gern noch an Diskussionen zu ThreadSafe :) Ich weiß ja nicht wie genau das hier genommen wird mit dem Markieren von Gelöstem. |
Re: Events in einem Thread
Zitat:
Lösung: TTimer im Hauptthread erstellen und im OnTimer den Workthread informieren (zB über Messages) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:54 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-2025 by Thomas Breitkreuz