Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Threads Suspend -> Resume ... wo gehts weiter? (https://www.delphipraxis.net/52241-threads-suspend-resume-wo-gehts-weiter.html)

gkoeder 25. Aug 2005 21:34


Threads Suspend -> Resume ... wo gehts weiter?
 
Hallo!

Ich beschäftige mich derzeit ein bisserl mit Threads und hab' da ein kleines Verständnisproblem:

Wenn ich einen Thread starte, führt diese die Prozedur 'Execute' aus. Sobald der Thread mit seiner Arbeit fertig ist (... die Execute-Prozedur durchlaufen ist), setze ich den Thread in den Suspended-State (Er pausiert also). Wenn ich nun den Thread mit Resume wieder zum Leben erwecke, wo fährt der Thread mit seiner arbeit fort? Startet er erneut die Execute-Prozedur oder arbeitet er einfach die nächste Zeile ab, wo ich ihn zuvor pausiert habe?

Greetings
Gerald

FastJack2 25. Aug 2005 21:54

Re: Threads Suspend -> Resume ... wo gehts weiter?
 
Er macht genau da weiter, wo du ihn suspended hast...
aber das lässt sich leicht hiermit herausfinden:

Code:
procedure TMeinThread.execute;
var
  i: integer;
begin
  while not terminated do
  begin
    form1.Memo1.Lines.Add(inttostr(i));
    i := i + 1;
    sleep(500);
  end;
end;
greetz
-FastJack2

Olli 25. Aug 2005 22:45

Re: Threads Suspend -> Resume ... wo gehts weiter?
 
Zitat:

Zitat von gkoeder
Wenn ich einen Thread starte, führt diese die Prozedur 'Execute' aus. Sobald der Thread mit seiner Arbeit fertig ist (... die Execute-Prozedur durchlaufen ist), setze ich den Thread in den Suspended-State (Er pausiert also). Wenn ich nun den Thread mit Resume wieder zum Leben erwecke, wo fährt der Thread mit seiner arbeit fort? Startet er erneut die Execute-Prozedur oder arbeitet er einfach die nächste Zeile ab, wo ich ihn zuvor pausiert habe?

Einen Thread benutzt man immer nur für wiederkehrende und/oder zyklische Probleme (Iterationen zB). Daher ist deine Execute-Methode ja üblicherweise eine Schleife. Wenn der Thread sich selber schlafenlegt, kannst du auch selber bestimmen, an welcher Stelle dies geschieht. Danach fährt er direkt hinter der Suspend-Anweisung fort.

Legst du den Thread von außen schlafen, kann man nicht sagen, wo er angehalten wird. Es kann zB mitten innerhalb einer Anweisung (auf HLL-Ebene) geschehen ... zB während ein Parameter bereits auf dem Stack liegt, der nächste aber noch nicht. Man kann es also nicht voraussagen, kann aber den Threadkontext holen und auch setzen (Rechte vorausgesetzt), wo unter anderen die aktuelle Adresse des EIP (Instruction Pointer) drinsteht.

BlackJack 26. Aug 2005 01:21

Re: Threads Suspend -> Resume ... wo gehts weiter?
 
ich habe das so verstanden dass er den thread wieder starten will nachdem die Execute-procedure abgearbeitet und schon wieder verlassen worden ist.
ich weiss allerdings gerade nicht ob man einen Thread, der mit der Execute-Methode fertig ist (und bei dem FreeOnTerminate auf False steht) so einfach mit Resume wieder von vorne starten kann (ich denke mal das wird nämlich der Threadersteller vorhaben).

edit: für dieses Vorhaben wäre auch das Event OnTerminate ganz nützlich.

chaosben 26. Aug 2005 05:28

Re: Threads Suspend -> Resume ... wo gehts weiter?
 
Wenn ich mal davon ausgehen darf, das es hier um eine beendete Execute-Prozedur geht, dann will ich hiermit dringlichst davon abraten, diese wieder per "Execute"-Aufruf zu starten. Dann verhält sie sich nämlich wie eine Prozedur und der ganze Vorteil eines Threads ist weg. Ich für meinen Teil mache das dann immer so:

Delphi-Quellcode:
procedure TThread.Execute();
begin
  while not Self.Suspended do
  begin
    //Machwas;
  end;
end;

Bitmap 26. Aug 2005 06:35

Re: Threads Suspend -> Resume ... wo gehts weiter?
 
Meiner Meinung nach macht ein Thread nur Sinn, wenn Du eine wiederholende Arbeit damit ausführst, sonnst kann man nämlich eine normales Objekt mit Methode für die Verarbeitung verwenden. Ich gehe mal davon aus dass Du auf einer Maschine mit nur einem Prozessor arbeitets, also eigentlich sowieso alles sequentiell abläuft.
Dann sollte eine Execute Methode so aussehen:
Delphi-Quellcode:
procedure TMeinThread.execute;
var
  i: integer;
begin
  while not terminated do
  begin
    form1.Memo1.Lines.Add(inttostr(i));
    i := i + 1;
    sleep(500);
  end;
end;
Von der logik her wird das System die While .. do Schleife solange durchlaufen, bis die Bedingung termineted auf true gesetzt wird.
Wenn nun von aussen die Methode suspend aufgerufen wird, hält der Thread genau an der Zeile an, wo er gerade war. Im obigen Fall wird das mit 99.99% Wahrscheinlichkeit bei der Zeile sleep(500) der Fall sein.
Falls Du an einer bestimmten stelle immer anhalten möchtest kannst Du Dir einfach folgendes Hilfskonstrukt in die execute Methode einbauen:

Delphi-Quellcode:
[b]procedure TMeinThread.SetSuspend;

begin
SuspendRequested:=true;
end;[/b]

procedure TMeinThread.execute;
var
  i: integer;
begin
  while not terminated do
  begin
    [b]form1.Memo1.Lines.Add(inttostr(i));[/b]
    if SuspendRequested then suspend;
    i := i + 1;
    sleep(500);
  end;
end;
Bei der Anweisung Terminate musst Du ebenfalls beachten, dass der Thread nicht sofort beendet wird, sondern lediglich das Property Termineted auf True gesetz wird. Somit läuft die Execute Methode nochmal bis zum Ende durch. Könnte unerwünschte Nebeneffekte haben.
Wenn Du FreeonTerminate auf True setzt um alles nachher aufgeräumt zu haben, solltest Du beachten, dass Threads die suspended sind niemals freigegeben werden, da die execute methode nicht zu ende laufen kann.
Dies müsstest Du ebenfalls selber ausprogrammieren, indem Du bei Terminate einen suspendeten Tread zuerst wieder resumest, damit er zuende laufen kann. Achtung bei verschachtelten Suspends, diese müssen ALLE wieder mit resume aufgehoben werden.

Hoffe das hilft Dir ein Bisschen weiter.

Viele Grüsse

Olli 26. Aug 2005 09:50

Re: Threads Suspend -> Resume ... wo gehts weiter?
 
Zitat:

Zitat von BlackJack
ich habe das so verstanden dass er den thread wieder starten will nachdem die Execute-procedure abgearbeitet und schon wieder verlassen worden ist.

Das geht nunmal nicht mit einem Thread. Ob der TThread das irgendwie kapselt um es zum Laufen zu bringen, weiß ich nicht.

Zitat:

Zitat von BlackJack
ich weiss allerdings gerade nicht ob man einen Thread, der mit der Execute-Methode fertig ist (und bei dem FreeOnTerminate auf False steht) so einfach mit Resume wieder von vorne starten kann (ich denke mal das wird nämlich der Threadersteller vorhaben).

Schwerlich, wenn man auf freigegebenen Speicher verweist ;)

Zitat:

Zitat von BlackJack
edit: für dieses Vorhaben wäre auch das Event OnTerminate ganz nützlich.

Warum nicht einfach einen Thread zweckgemäß verwenden statt seine eigenen Vorstellungen um jeden Willen durchzusetzen? :zwinker: ... die Fensterschleife wird auch nicht serieller, nur weil man sie nicht als Schleife haben will ...

Zitat:

Zitat von chaosben
Wenn ich mal davon ausgehen darf, das es hier um eine beendete Execute-Prozedur geht, dann will ich hiermit dringlichst davon abraten, diese wieder per "Execute"-Aufruf zu starten.

:thumb: so ist es ...

Zitat:

Zitat von chaosben
Delphi-Quellcode:
procedure TThread.Execute();
begin
  while not Self.Suspended do
  begin
    //Machwas;
  end;
end;

Ich benutze zwar kein TThread, würde es aber so machen:
Delphi-Quellcode:
procedure TThread.Execute();
begin
  while not Terminated do
  begin
    //Machwas;
    Suspend(); // Am Ende der Schleife schlafenlegen ...
  end;
end;
... wie oben beschrieben. So kann man garantieren, daß erst ein Schleifendurchlauf durch ist, bevor man wieder neu beginnt (durch Resume von außen). Außerdem sollte die Suspended-Property nur von außen Sinn machen, da Execute ja nicht ausgeführt wird und damit auch nicht die Prüfung ob Suspended oder nicht. Man könnte es also genausogut durch ein while(true)do; ersetzen ;)

Zitat:

Zitat von Bitmap
Wenn nun von aussen die Methode suspend aufgerufen wird, hält der Thread genau an der Zeile an, wo er gerade war.

Bei Hochsprachen (HLLs) kann man das so nicht sagen, da eine Zeile meistens vielen Assemblermnemonics entspricht.

Zitat:

Zitat von Bitmap
Im obigen Fall wird das mit 99.99% Wahrscheinlichkeit bei der Zeile sleep(500) der Fall sein.

Genauer: davor oder dahinter, weil Sleep dem Scheduler sagt, daß dieser Thread soundsolange keine Zeit aus der Zeitscheibe zugeteilt bekommen soll. Damit wird der Thread sozusagen hinten in die Warteschlange gestellt. Dies ist auch bei Sleep(0) der Fall, welches nur die komplette Rechenzeit des Threads an den nächsten Thread der Zeitscheibe abgibt - aber auch beim nächsten Durchlauf wieder diesen Thread drannimmt.

Zitat:

Zitat von Bitmap
Wenn Du FreeonTerminate auf True setzt um alles nachher aufgeräumt zu haben, solltest Du beachten, dass Threads die suspended sind niemals freigegeben werden, da die execute methode nicht zu ende laufen kann.

Daher würde ich FreeonTerminate außerhalb der Schleife in der Execute-Methode aufrufen. Damit kann man alle Vorteile daraus ziehen, hat aber keine Nachteile.

Luckie 26. Aug 2005 10:05

Re: Threads Suspend -> Resume ... wo gehts weiter?
 
Zitat:

Zitat von Olli
Daher würde ich FreeonTerminate außerhalb der Schleife in der Execute-Methode aufrufen. Damit kann man alle Vorteile daraus ziehen, hat aber keine Nachteile.

FreeOnTerminate ist keine Methode zum Aufrufen, sondern eine Eigenschaft, die entweder True oder False sein kann.

Olli 26. Aug 2005 10:31

Re: Threads Suspend -> Resume ... wo gehts weiter?
 
Zitat:

Zitat von Luckie
FreeOnTerminate ist keine Methode zum Aufrufen, sondern eine Eigenschaft, die entweder True oder False sein kann.

Das ist mir schon klar. Dann rufst du eben "FreeOnTerminate := True" auf ... ich dachte ich sei pedantisch :roll:

Luckie 26. Aug 2005 10:33

Re: Threads Suspend -> Resume ... wo gehts weiter?
 
Normalerweiser erzeugt man das Thread-Objekt um angahltenen Zustand, setzt dann die Eigenschaften, unteranderem eben auch FreeOnTerminate, und ruft dann die Methode Resume auf.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:28 Uhr.
Seite 1 von 2  1 2      

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