Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Thread soll eine Minute warten: Sleep oder Timer? (https://www.delphipraxis.net/128591-thread-soll-eine-minute-warten-sleep-oder-timer.html)

Bbommel 2. Feb 2009 11:38


Thread soll eine Minute warten: Sleep oder Timer?
 
Hallo zusammen,

nachdem ich mich jahrelang um Threads herumdrücken konnte (außer vor ein paar Jahren in der Uni in der Theorie), komme ich nun an dem Thema wohl nicht mehr vorbei, da ich in einem Projekt eine periodische Datenbank-Abfrage implementieren möchte, die den Benutzer aber nicht weiter stören soll. Konkret soll also einmal pro Minute eine MSSQL-Datenbank abgefragt werden und nur, falls dort bestimmte Informationen vorliegen, soll der Benutzer bei seiner eigentlichen Arbeit gestört werden.

Ich habe nun noch ein Konstruktions- bzw. Verständnisproblem. Wie schaffe ich es am elegantesten, dass der Thread einerseits eine Minute lang nix macht, nachdem die Datenbank abgefragt wurde, andererseits aber dennoch ziemlich schnell terminiert wird, sobald der Hauptthread das wünscht (weil das Programm beendet wird oder aus anderen Gründen). Denn: Wenn man den Thread mit "sleep" Schlafen schickt, bekommt er von einem Terminate ja erst mal nix mehr mit.

Ich hab hier in der DP schon ein bisschen geschmökert, was mir auch die eine oder andere Idee gebracht hat, aber so richtig sicher bin ich mir noch nicht, was nun die "ultimative" Lösung ist (obwohl ich jetzt eher erwartet hätte, dass das ein Standard-Problem wäre - nicht richtig gesucht?) :) Wobei ich jetzt beim Tippen das Gefühl bekommen habe, auf einem guten Weg zu sein...

Ich hab mir mal ein kleines Beispiel gebastelt, das mit Datenbanken noch gar nix macht (ist ja auch nicht mein eigentliches Problem... hoffentlich) und mit dem sich die Überlegungen ganz gut zeigen lassen:

Die Thread-Klasse:

Delphi-Quellcode:
unit thread;

interface

uses
  Classes, SyncObjs;

type
  TCalcThread = class(TThread)
  private
    { Private-Deklarationen }
    resultText: string;
  protected
    procedure Execute; override;
    procedure ShowResult;
  public
    calcValue: integer;
    constructor Create(CreateSuspended: Boolean);
  end;

var CriticalParams : TCriticalSection;

implementation

uses main, sysUtils;

{ Wichtig: Methoden und Eigenschaften von Objekten in visuellen Komponenten dürfen
  nur in einer Methode namens Synchronize aufgerufen werden, z.B.

      Synchronize(UpdateCaption);

  und UpdateCaption könnte folgendermaßen aussehen:

    procedure TCalcThread.UpdateCaption;
    begin
      Form1.Caption := 'Aktualisiert in einem Thread';
    end; }

{ TCalcThread }

procedure TCalcThread.ShowResult;
begin
  thread1_main.LabelResult.Caption:=resultText;
end;

procedure TCalcThread.Execute;
var myValue: integer;
begin
  { Thread-Code hier einfügen }
  while not terminated do begin
    CriticalParams.Acquire;
    myValue:=calcValue;
    CriticalParams.Release;

    if myValue=-1 then
      resultText:='nix gesetzt.'
    else
      resultText:=intToStr(myValue*80);
    Synchronize(ShowResult);
    sleep(10000);
  end;
end;

constructor TCalcThread.Create(CreateSuspended: Boolean);
begin
  inherited;

  calcValue:=-1;
end;

end.
(damit ich beim Testen nicht ewig warten muss, legt sich der Thread hier nur 10 Sekunden Schlafen)

Im Hauptprogramm gibt es nun einen Button, mit dem man den Thread beenden kann:

Delphi-Quellcode:
procedure Tthread1_main.ButtonStopThreadClick(Sender: TObject);
begin
  theThread.Terminate;

  // warten bis der Thread beendet wurde...
  theThread.WaitFor;
  messageDlg('Der Thread ist durch.',mtInformation,[mbOk],0);
  theThread.Free;
  theThread:=nil;
end;
Das Problem sollte klar sein: Es kann bis zu 10 Sekunden dauern, bis der Thread nach dem Klick auf den Button wirklich beendet wird. Am einfachsten wäre es ja, wenn man das sleep irgendwie von außen unterbrechen könnte - also das Hauptprogramm schickt einen Weckruf, der den Wecker einfach etwas vorstellt, aber sowas habe ich nicht gefunden. Also wird man wohl drumrum basteln müssen...

Am einfachsten wäre es wahrscheinlich, wenn man nicht 10 Sekunden wartet, sondern 10 mal eine Sekunde, so dass aus
Delphi-Quellcode:
    sleep(10000);
ein
Delphi-Quellcode:
i:=0
while (not terminated) and (i<10) do begin
  sleep(1000);
  inc(i);
end;
würde. Der Hauptthread bekäme dann wohl viel schneller eine Rückmeldung, aber irgendwie fühlen sich diese ständigen Wechsel in den Thread nicht so richtig gut an. Hat irgendwie was vom aktiven Warten.

Als andere Alternative wollte ich jetzt eigentlich vorschlagen, dass ein Timer den Thread periodisch freigibt und neu erzeugt, aber beim Schreiben kam mir jetzt gerade der Gedanke, dass ein Timer wahrscheinlich ein guter Ansatz ist, aber ein Suspend/Resume wahrscheinlich besser, als das Dingen zu zerstören und neu anzulegen.

Das heißt, die Execute-Methode vom Thread sähe dann so aus:

Delphi-Quellcode:
procedure TCalcThread.Execute;
var myValue: integer;
begin
  { Thread-Code hier einfügen }
  while not terminated do begin
    CriticalParams.Acquire;
    myValue:=calcValue;
    CriticalParams.Release;

    if myValue=-1 then
      resultText:='nix gesetzt.'
    else
      resultText:=intToStr(myValue*80);
    Synchronize(ShowResult);
    Suspend;
  end;
end;
Und im Hauptthread gibt es dann ein Timer-Ereignis und eine Änderung beim Klicken auf den Button:

Delphi-Quellcode:
procedure Tthread1_main.TimerThreadTimer(Sender: TObject);
begin
  theThread.Resume;
end;

procedure Tthread1_main.ButtonStopThreadClick(Sender: TObject);
begin
  TimerThread.Enabled:=false;
  theThread.Terminate;
  theThread.Resume; // damit das Dingen auch merkt, dass er beendet wurde...

  // warten bis der Thread beendet wurde...
  theThread.WaitFor;
  messageDlg('Der Thread ist durch.',mtInformation,[mbOk],0);
  theThread.Free;
  theThread:=nil;
end;
Ist da irgendein Denkfehler drin oder ist das die "ultimative Lösung", nach der ich gesucht habe? Mir kommt sie gerade eigentlich ganz gut vor. :dancer:

Ich bin auf eure Rückmeldungen gespannt.

Danke und bis denn
Bbommel

sirius 2. Feb 2009 11:46

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
In einem Thread ist sleep nutzbar (nur auf Terminate sollte man achten). Besser ist waitforsingleobject mit einer Zeitangabe.

Edit:
Waitforsingleobject irgendwie so:
Delphi-Quellcode:
constructor Tmythread.Create(CreateSuspended: Boolean);
begin
  inherited Create(false);
  FEvent:=TEvent.Create(nil,true,false,'');
end;

destructor Tmythread.Destroy;
begin
  FEvent.Free;
  inherited;
end;

procedure Tmythread.DoSomething;
begin
  //abstract ;-)
end;

procedure Tmythread.Terminate;
begin
  inherited;
  FEvent.SetEvent;
end;

procedure Tmythread.execute;
begin
  while not terminated do
  begin
    DoSomething;
    FEvent.ResetEvent;
    FEvent.WaitFor(10000);
  end;
end;

nuclearping 2. Feb 2009 11:46

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Denke mal, dass das auch mit GetTickCount gehen sollte. AFAIK ist das Threadsafe.

Reinhard Kern 2. Feb 2009 11:54

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Hallo,

wie wärs denn mit KISS (keep it simple and stupid):

Das Programm wartet nur darauf, beendet zu werden.

Die Funktionalität wird im Timer Service erledigt, falls was vorliegt.

Weder Thread noch sleep nötig.

Gruss Reinhard

himitsu 2. Feb 2009 11:54

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
ich würde vielleicht nich direkt ein 60-Sekunden-Sleep einbauen, denn so kannst du den Thread nicht mehr so schön/schnell beenden. (vorallem wenn das Programm beendet werden soll ... wär ja blöd, wenn du dann im schlimmsten Fall noch 'ne Minute gewartet werden müßte)

CPU-schonend und unterbrechbar wäre z.B. sowas:
Delphi-Quellcode:
Var T: LongWord;
  ThreadSollBeendetWerden: Boolean;
...

T := GetTickCount;
While (GetTockCount - T < 60000) and not ThreadSollBeendetWerden do
  Sleep(200);
oder was mit WaitFor... wie sirius grad nachtrug

Bbommel 2. Feb 2009 12:03

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Zitat:

Zitat von sirius
In einem Thread ist sleep nutzbar (nur auf Terminate sollte man achten). Besser ist waitforsingleobject mit einer Zeitangabe.

Also sollte ich innerhalb des Threads das
Delphi-Quellcode:
sleep(10000)
durch ein
Delphi-Quellcode:
waitForSingleObject(Handle,10000);
ersetzen?

So ganz schlau werde ich daraus noch nicht - jetzt bei diesem Versuch wartet der Thread ja, bis er selbst signalisiert (also beendet, wenn ich das richtig verstanden habe) wird. Aber das bringt mich offenbar nicht so richtig weiter oder kann man dieses Signal auch manuell senden? Oder muss ich da einen extra Handler für erstellen?

Ich hatte zu dem Thema auch schon im Thread-Tutorial von Luckie was gelesen, aber dort werden die wait-Funktionen ja gerade auch außerhalb des Threads eingesetzt, was ja auf mein Problem nicht so recht zutrifft.

Bis denn
Bommel

sirius 2. Feb 2009 12:09

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Ähm, das zuerst gedachte Edit oben sollte hier als Antwort hin.

Bbommel 2. Feb 2009 12:11

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Zitat:

Zitat von himitsu
ich würde vielleicht nich direkt ein 60-Sekunden-Sleep einbauen, denn so kannst du den Thread nicht mehr so schön/schnell beenden.

Jepp, genau das ist ja mein Problem.

Zitat:

Zitat von himitsu
CPU-schonend und unterbrechbar wäre z.B. sowas:

[...]
Nur zum Verständnis noch mal nachgefragt: Das ist ja eigentlich der gleiche Ansatz, wie ich ihn mit dem mehrfachen Hochzählen von i und dazwischen einem kürzeren sleep hatte, nur über den TickCount eleganter, weil die 60 Sekunden besser eingehalten werden können, richtig?

Mein Problem mit dem Ansatz ist nur, dass es sich komisch "anfühlt", wenn andauernd ein Kontextwechsel gemacht wird, obwohl eigentlich gar nichts zu tun ist. Ich kann nur überhaupt nicht einschätzen, ob sowas auch tatsächlich nach bemerkbar ist oder ob ich mir dann den Kopf über ein eher akademisches Problem zerbreche. :)

Bis denn
Bommel

Bbommel 2. Feb 2009 12:13

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Zitat:

Zitat von sirius
Ähm, das zuerst gedachte Edit oben sollte hier als Antwort hin.

Okay, ich denke es mir einfach hier hin als Antwort auf meine Rückfrage. Sieht gut aus, Danke dir.

Bis denn
Bommel

Zoot 2. Feb 2009 12:13

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Zitat:

Zitat von Reinhard Kern
Hallo,

wie wärs denn mit KISS (keep it simple and stupid):

Das Programm wartet nur darauf, beendet zu werden.

Die Funktionalität wird im Timer Service erledigt, falls was vorliegt.

Weder Thread noch sleep nötig.

Gruss Reinhard

Verstehe auch nicht, wozu man einen Thread braucht, wenn der eh normalerweise nix tut.
Ein simpler timer reicht doch dann völlig.

nuclearping 2. Feb 2009 12:14

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
GetTickCount ist Windows API und fragt die Millisekunden seit dem letzten Systemstart ab. Da unterbricht nix.

Bbommel 2. Feb 2009 12:17

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Zitat:

Zitat von Zoot
Zitat:

Zitat von Reinhard Kern
Hallo,
Weder Thread noch sleep nötig.

Verstehe auch nicht, wozu man einen Thread braucht, wenn der eh normalerweise nix tut.
Ein simpler timer reicht doch dann völlig.

Weil das nur ein stark vereinfachtes Beispiel war, bei dem es mir um das Problem mit dem sauberen Beenden ging. Im realen Programm wird es um eine Datenbank-Abfrage gehen. Und wenn man das schon mal gemacht hat, weiß man, dass Verbindungsaufbau und/oder Abfrage gerne mal ein paar Sekunden dauern. Da wäre es für den Anwender nicht so schön, wenn ihm plötzlich die Anwendung einfriert, obwohl er nix gemacht hat.

Jetzt klarer?

Bis denn
Bommel

Reinhard Kern 2. Feb 2009 12:29

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Zitat:

Zitat von Bbommel
Zitat:

Zitat von Zoot
Zitat:

Zitat von Reinhard Kern
Hallo,
Weder Thread noch sleep nötig.

Verstehe auch nicht, wozu man einen Thread braucht, wenn der eh normalerweise nix tut.
Ein simpler timer reicht doch dann völlig.

Weil das nur ein stark vereinfachtes Beispiel war, bei dem es mir um das Problem mit dem sauberen Beenden ging. Im realen Programm wird es um eine Datenbank-Abfrage gehen. Und wenn man das schon mal gemacht hat, weiß man, dass Verbindungsaufbau und/oder Abfrage gerne mal ein paar Sekunden dauern. Da wäre es für den Anwender nicht so schön, wenn ihm plötzlich die Anwendung einfriert, obwohl er nix gemacht hat.

Jetzt klarer?

Bis denn
Bommel

Hallo Bommel,

welche Anwendung soll denn einfrieren? Das Hauptprogramm bekommt nur Messages zum Beenden und führt diese sofort aus, oder Timer-Messages und zeigt dann Daten an oder was auch immer, was man vernünftigerweise sowieso nicht unterbricht. Ausserdem kann man das leicht gegeneinander sperren, so dass nur beendet wird, wenn gerade keine Daten verarbeitet werden, und man kann die Datenverarbeitung abbrechen, wenn das Programm beendet werden soll, beides hat nichts mit Threads zu tun.

Der grösste Nachteil meiner Lösung, das muss ich zugeben, ist, dass man nicht damit angeben kann, was für tolle Multithreads man schreiben kann. Mit einfachen Lösungen macht man sich hier hochgradig unbeliebt. Also vergiss es einfach und mach einen, zwei, viele Threads.

Gruss Reinhard

himitsu 2. Feb 2009 12:31

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Zitat:

Zitat von Bbommel
Nur zum Verständnis noch mal nachgefragt: Das ist ja eigentlich der gleiche Ansatz, Wie ich ihn mit dem mehrfachen Hochzählen von i und dazwischen einem kürzeren sleep hatte, nur über den TickCount eleganter, weil die 60 Sekunden besser eingehalten werden können, richtig?

genau :angel:

Zitat:

Zitat von Bbommel
Mein Problem mit dem Ansatz ist nur, dass es sich komisch "anfühlt", wenn andauernd ein Kontextwechsel gemacht wird, obwohl eigentlich gar nichts zu tun ist. Ich kann nur überhaupt nicht einschätzen, ob sowas auch tatsächlich nach bemerkbar ist oder ob ich mir dann den Kopf über ein eher akademisches Problem zerbreche. :)

Also nach meinen Erfahrungen/Tests sind, je nach Einsatzgebiet, 50-200ms für den Menschen kaum merkbar und für den Prozessor sind die Intervalle wiederum so groß, daß diese ihn auch nicht sehr stören.

Ich halte beides für "gute" Möglichkeiten dieses zu regeln (WaitFor und soeine kleine Sleep-Schleife) ... es kommt nur darauf an, wieviel du implementieren willst und wie schnell das Abbrechen Programmintern sein soll ... das WaitFor... reagiert natürlich schneller, ist aber 'nen Hauch aufwendiger.

Bbommel 2. Feb 2009 12:48

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Zitat:

Zitat von Reinhard Kern
welche Anwendung soll denn einfrieren? Das Hauptprogramm bekommt nur Messages zum Beenden und führt diese sofort aus, oder Timer-Messages und zeigt dann Daten an oder was auch immer, was man vernünftigerweise sowieso nicht unterbricht.

Es geht mir aber doch nicht um das Anzeigen der Daten - da hast du recht, das sollte ausreichend schnell sein und auch nicht unterbrochen werden - sondern um das BESCHAFFEN der Daten. Würde ich das ohne Threads, sondern direkt im Timer machen, dann würde der Benutzer in einem Moment ganz normal mit dem Programm arbeiten können und im nächsten Moment reagiert das Programm nicht mehr, weil gerade versucht wird, eine Verbindung zu einem Datenbank-Server aufzubauen (der ja vielleicht sogar im schlimmsten Fall nicht erreichbar ist). Während dieser 3-10 Sekunden würde die Anwendung aus Sicht des Benutzers stehen, der sich wundert, was er falsch gemacht hat.

Das Aktualisieren der Komponenten, also das Anzeigen der Daten, geschieht dann natürlich wieder über den Hauptthread.

Ich sehe nicht, wo ich da gerade zu kompliziert denke und wie man das einfacher lösen könnte. Aber wenn ich mich da irgendwie verrannt habe und du eine einfachere Lösung siehst, gerne her damit.

Bis denn
Bommel

sirius 2. Feb 2009 13:09

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Zitat:

Zitat von Reinhard Kern
beides hat nichts mit Threads zu tun.

Aber, wie der OP schon schrieb, Datenbankabfragen gehören sehr wohl in Threads. Ich verstehe gar nicht, was es darüber zu diskutieren gibt.

Dezipaitor 2. Feb 2009 13:14

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Ich bin für
WaitForSingleObject(hStopThreadevent, 20*1000)

Frederika 2. Feb 2009 18:27

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Zitat:

Zitat von Bbommel
Würde ich das ohne Threads, sondern direkt im Timer machen, dann würde der Benutzer in einem Moment ganz normal mit dem Programm arbeiten können und im nächsten Moment reagiert das Programm nicht mehr, weil gerade versucht wird, eine Verbindung zu einem Datenbank-Server aufzubauen (der ja vielleicht sogar im schlimmsten Fall nicht erreichbar ist). Während dieser 3-10 Sekunden würde die Anwendung aus Sicht des Benutzers stehen, der sich wundert, was er falsch gemacht hat.

Ne, die normale Lösung ist eigentlich, einen Timer im Hauptprogramm zu haben, der dann jeweils einen Thread startet. Der Thread selbst beendet sich immer sofort nach erledigter Aufgabe. Da muß niemand auf irgendwas warten.

sirius 2. Feb 2009 20:31

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Zitat:

Zitat von Frederika
Ne, die normale Lösung ist eigentlich, einen Timer im Hauptprogramm zu haben, der dann jeweils einen Thread startet. Der Thread selbst beendet sich immer sofort nach erledigter
Aufgabe. Da muß niemand auf irgendwas warten.

Dazu würde ich gern nähere Gründe wissen.
Gerade bei Datenbankanwendungen mache ich es auch, dass ich einen Thread habe, welcher die komplette Datenbankkommunikation betreibt. Wenn grad mal nix zu tun ist, dann schläft er halt. Bei mir ist allerdings alles komplett ereignisgesteuert, aber das steht ja hier nicht zum Thema. Warum sehe ich da bei Datenbanken die Notwendigkeit? Der Thread soll eine Verbindung zur Datenbank aufbauen. Und diese Verbindung soll über längere Zeiten (auch wenn grad keine Query o.ä. abgearbeitet wird) bestehen. Und wenn ich die Verbindung nicht unterbrechen will, kann ich auch nicht den Thread wegschmeißen. Dazu muss ich ihn halt schlafen legen. Warum will ich die Verbindung aufrecht erhalten. Z.B. wegen bestehenden Transaktionen (mit Rollback-Option). Oder bei Oracle-Packages wird je Session eine Instanz des "Package-Objektes" angelegt. Die Instanz benötige ich über längere Zeit. Dann gibt es noch Userverwaltungen, welche auf einer konstanten Verbindung zu Clients beruhen....

Dezipaitor 2. Feb 2009 20:33

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Sowas?
WaitForMultipleObjects(hAnyEvent, hThreadStopEvent, ... , YourTimeOut)

sirius 2. Feb 2009 20:42

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Zitat:

Zitat von Dezipaitor
Sowas?

Ähm...Das war meine erste Antwort

Dezipaitor 2. Feb 2009 20:49

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Dein Edit habe ich nicht mehr gelesen.

Bbommel 3. Feb 2009 08:16

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Hallo zusammen,

Danke euch allen für die Anregungen und auch die Diskussionen - das alles hat mir nicht nur für die eigentliche Umsetzung, sondern auch für das Wissen, warum ich das eigentlich tue, weitergeholfen.

Einen hab ich aber noch. ;) Am Anfang hatte ich selbst noch eine Lösung vorgeschlagen, auf die niemand weiter eingegangen ist (wie gemein... ;) ). Das war der Ansatz, in dem sich der Thread am Ende mit Suspend selbst Schlafen gelegt hat und dann von außen wieder durch einen Timer aufgeweckt wurde. Wenn man das mit den anderen Beiträgen hier vergleicht, ist das ja fast so eine Art Zwischending zwischen dem Vorschlag von sirius (und anderen) und Frederika. Ist an dem Ansatz etwas wirklich falsch? Ist ein Timer ineffektiver als ein WaitFor? Oder ist er einfach nur unschön oder ungewöhnlich?

Bis denn
Bommel

Bbommel 3. Feb 2009 09:59

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Hallo Sirius, hallo zusammen,

eine Nachfrage habe ich noch zu deinem Ansatz.

Zitat:

Zitat von sirius
Delphi-Quellcode:
constructor Tmythread.Create(CreateSuspended: Boolean);
begin
  inherited Create(false); // <----- muss das wirklich "false" sein?
  FEvent:=TEvent.Create(nil,true,false,'');
end;

[...]

procedure Tmythread.execute;
begin
  while not terminated do
  begin
    DoSomething;
    FEvent.ResetEvent; // <----- ist das hier wirklich sinnvoll?
    FEvent.WaitFor(10000);
  end;
end;

Es geht mir um die markierten Stellen:

1. Create: Du rufst den Vorgänger immer mit "false" auf - machst du das, weil sonst die Gefahr besteht, dass das Execute schon losrennt, bevor das Create durch ist? Das heißt, wenn ich will, dass der Parameter noch weiter beachtet wird, müsste das Create vollständig so aussehen:
Delphi-Quellcode:
constructor Tmythread.Create(CreateSuspended: Boolean);
begin
  inherited Create(false);
  FEvent:=TEvent.Create(nil,true,false,'');

  if not CreateSuspended then
    Resume;
end;
Edit: Da hatte ich wohl Tomaten auf die Augens und true und false verwechselt ;) - Die richtige Frage wäre also: Warum startest du den Thread IMMER als nicht-suspended?

2. ResetEvent: Ist das nicht eher störend? Das Event startet doch durch die Parameter bei Create eh als nicht gesetzt. Durch dieses Reset könnte doch nun folgendes passieren: Nehmen wir an, DoSomething dauert ein paar Sekunden (eben jene Datenbank-Abfrage beispielsweise) und während diese DoSomething läuft, wird der Thread terminiert und damit das Event gesetzt. Nach dem DoSomething wird es aber erst mal zurückgesetzt, was bedeutet, dass noch mal 10 Sekunden lang ein WaitFor aufgerufen wird, obwohl man das eigentlich gar nicht mehr braucht. Oder? Mein (sinnloser) Demo-Thread funktioniert jedenfalls auch ohne das Reset genau wie gewünscht.

Verzeiht meine vielen Nachfragen. Wie gesagt, ich bin halt noch neu im Thema Threads und möchte so gut wie möglich verstehen, was ich da tue, bevor ich das in Produktiv-Systeme einbaue.

Bis denn
Bommel

sirius 3. Feb 2009 10:01

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Suspend und Resume sollte man nicht verwenden (wird zwar intern von TThread verwendet, aber egal). Ist laut msdn auch nur für das Debuggen von Processen und Threads gedacht.
Zitat:

Zitat von msdn
[SuspendThread]
This function is primarily designed for use by debuggers. It is not intended to be used for thread synchronization. ...

Das Waitfor bzw. die vernwednete Klasse TEvent, entspricht der Idee ein Ereignis zu setzen und mit Waitforsingleobject auf das Ereignis oder die verstrichene Zeit zu warten. TEvent kapselt die Funktionen der WinAPI (u.a. waitforsingleobject wird zur Methode TEvent.WaitFor)
Der Vorschlag mit dem Timer ist, dass du jedesmal einen neuen Thread und damit eine neue Verbindung aufbaust.

[roter Kasten] lese ich mir gleich durch


Edit: zum roten Kasten (letzter Beitrag)
Punkt 1. Jep das war falsch. das muss inherited Create(CreateSupended) hin. Der Thread wird so oder so fühestens erst nach dem Constructor gestartet.

Punkt 2. Hmm ja, müsste man nochmal genauer drüber nachdenken. bzw. wenn ich nochmal drüber nachdenke --> ja kann man streichen. Ich arbeite häufig mit mehreren Events, und da muss ich hin und wieder zurücksetzen.

Bbommel 3. Feb 2009 10:20

Re: Thread soll eine Minute warten: Sleep oder Timer?
 
Alles klar. Vielen Dank noch mal, jetzt kann es dann so langsam ans echte Projekt gehen. :dp:

Stefan1286b 13. Mär 2021 17:59

AW: Thread soll eine Minute warten: Sleep oder Timer?
 
Das Thema ist schon etwas älter aber ich habe es so gelöst:

Code:
constructor TBThread.Create;
begin
  inherited Create(true);
  FTerminateEvent := CreateEvent(nil, true, False, nil);
end;

destructor TBThread.Destroy;
begin
  SetEvent(FTerminateEvent);
  CloseHandle(FTerminateEvent);
  inherited;
end;

procedure TBThread.Execute;
begin
  while not Terminated do
  begin
      if WaitForSingleObject(FTerminateEvent, fcint) = WAIT_TIMEOUT then
    begin
      if not Terminated then
        DoSomething;
    end;
  end;
end;

procedure TBThread.TerminatedSet;
begin
  inherited;
  SetEvent(FTerminateEvent);
end;
fcint ist die Zeit die der Thread warten soll.
Und durch dass Event welches durch die überschriebene Methode TerminatedSet gesetzt wird wird das warten vorzeitig beendet.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:38 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