AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Events in einem Thread

Ein Thema von ThorvdA · begonnen am 30. Mai 2010 · letzter Beitrag vom 13. Mär 2021
Antwort Antwort
Seite 1 von 2  1 2   
ThorvdA

Registriert seit: 25. Apr 2006
6 Beiträge
 
#1

Events in einem Thread

  Alt 30. Mai 2010, 13:17
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:
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;
Wie ich natürlich bemerken musste läuft das TimerEvent innerhalb meines Hauptthreads ab und blockiert mein Formular.
Was kann ich dagegen tun? Das ganze ist nur Beispielhaft, ich stehe häufiger vor dieser Art von Problem.

Grüße!
  Mit Zitat antworten Zitat
Benutzerbild von wicht
wicht

Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
 
Delphi XE Professional
 
#2

Re: Events in einem Thread

  Alt 30. Mai 2010, 13:51
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;
http://streamwriter.org

"I make hits. Not the public. I tell the DJ’s what to play. Understand?"
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: Events in einem Thread

  Alt 30. Mai 2010, 14:13
Du darfst die Komponenten (hier timer) erst in Execute erstellen. Allerdings brauchst du hier eine Hier im Forum suchenMessageschleife
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
ThorvdA

Registriert seit: 25. Apr 2006
6 Beiträge
 
#4

Re: Events in einem Thread

  Alt 30. Mai 2010, 14:53
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.
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#5

Re: Events in einem Thread

  Alt 30. Mai 2010, 15:07
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:
  1. GetMessage oder WaitMessage (wartet nur auf Windows-Messages)
  2. WaitForSingleObject, WaitForMultipleObjects (wartet auf Threads, Windows-Events, Mutex, Sempahore, Processe)
  3. MsgWaitForMultipleObjects (wartet auf beides 1 und 2 )
  4. ...andere blockierende Funktionen, bspw von den Sockets, die man nicht untereinander mischen kann

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,
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
ThorvdA

Registriert seit: 25. Apr 2006
6 Beiträge
 
#6

Re: Events in einem Thread

  Alt 30. Mai 2010, 15:24
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:
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;
Das Event kommt an, allerdings muss ich selbst darauf reagieren, oder?
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?
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#7

Re: Events in einem Thread

  Alt 30. Mai 2010, 19:52
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:
repeat
  while GetMEssage(msg,...) do
    Dispatchmessage(msg);
 //hier noch etwas anderes tun
until terminated;
...könnte es zu einem Laufzeitproblem kommen, wenn du erst WM_Quit setzt und dann FTerminated auf True.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#8

Re: Events in einem Thread

  Alt 31. Mai 2010, 06:43
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:

AllocateHwnd is not Thread-Safe
  Mit Zitat antworten Zitat
ThorvdA

Registriert seit: 25. Apr 2006
6 Beiträge
 
#9

Re: Events in einem Thread

  Alt 31. Mai 2010, 23:29
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.
  Mit Zitat antworten Zitat
dominikkv

Registriert seit: 30. Sep 2006
Ort: Gundelfingen
1.109 Beiträge
 
Delphi 2007 Professional
 
#10

Re: Events in einem Thread

  Alt 1. Jun 2010, 12:35
Zitat von ThorvdA:
@samso:
Dann funktioniert es aber leider nichtmehr (bzw der falsche Thread führt TimerEvent aus)...
Andersherum funktioniert es aber auch nicht! Bzw vielleicht scheint es zu funktionieren, wunder dich aber nicht, wenn du in einem großen Projekt plötzlich an den verschiedensten Stellen Fehlermeldungen bekommst. Und dann viel Spaß beim Debuggen!

Lösung: TTimer im Hauptthread erstellen und im OnTimer den Workthread informieren (zB über Messages)
Dominik
Wer anderen eine Grube gräbt, hat ein Gruben-Grab-Gerät!
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:19 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