Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Thread: Suspend und Resume deprecated (https://www.delphipraxis.net/166260-thread-suspend-und-resume-deprecated.html)

MiKaEr 4. Feb 2012 21:45

Thread: Suspend und Resume deprecated
 
hallo,

ich beschäftige mich schon länger mit threads. jedoch habe ich eine wichtige frage:
wenn ich einen thread starte und danach pausiere, mache ich das per suspend. das ist aber deprecated. was nutze ich alternativ:

noch wichtiger:
ich erwecke ihn nachher wieder mit resume. das ist aber auch deprecated. es wird empfohlen, stattdessen start zu nehmen. aber wenn ein thread bereits gestartet wurde unc ich nach suspend > start verwende, bekomme ich eine AV. ich kann einen gestartetetn thread nicht erneut starten, das ist das problem.

was ist die funktionierende alternative zu resume?

himitsu 4. Feb 2012 21:50

AW: Thread: Suspend und Resume deprecated
 
Das macht man eben nicht! :warn:

Genau deswegen ist Suspend auch endlich deprecated.

Denn von außerhalb kann man nicht sicherestellen, daß der Thread in einem "sicheren" Zustand angehalten wird.
Das kannst du maximal von innerhalb des Threads sicherstellen, indem er sich selber anhält, an einer definierten Stelle,
oder wenn er von Anfang an Suspend ist (Parameter im Constructor).

silver-moon-2000 4. Feb 2012 21:53

AW: Thread: Suspend und Resume deprecated
 
Zitat:

Zitat von MiKaEr (Beitrag 1149281)
wenn ich einen thread starte und danach pausiere, mache ich das per suspend. das ist aber deprecated.

ich erwecke ihn nachher wieder mit resume. das ist aber auch deprecated.

Hallo,

also ich nutze dazu immer eine Variable, die eben in Execute abgefragt und "von außen" gesetzt wird

Delphi-Quellcode:
type TMyThread = class(TThread)
  private
    FSleep     : Boolean;
    FTerminated : Boolean;
  public
    procedure Execute; override;
    procedure GoToSleep;
    procedure WakeUp;
end;

procedure TMyThread.Execute;
begin
  while not (FTerminated) do
  begin
    if not (FSleep) do
    begin
      //Befehle abarbeiten
    end
    else
      Sleep(10);
  end;
end;

procedure TMyThread.GoToSleep;
begin
  FSleep := True;
end;

procedure TMyThread.WakeUp;
begin
  FSleep := False;
end;
nach bestem Wissen und Gewissen, aber ohne IDE aus dem Kopf runtergeschrieben

OK, das ist ein klein wenig anders, als den Thread wirklich "stillzulegen", aber wenn ich mich richtig erinnere, dann wurde dieses Verfahren auch hier schon empfohlen

edit2: richtig, hier war's gewesen
http://www.delphipraxis.net/149714-w...-veraltet.html

edit:
Huch, der rote Kasten war zwar da, aber meine Meinung will ich Euch trotzdem nicht vorenthalten

mjustin 5. Feb 2012 08:52

AW: Thread: Suspend und Resume deprecated
 
Eine alternative Lösung für das Suuspend / Resume Problem ist in den Indy Komponenten in der Unit IdThread enthalten.

Sie enthält eine Threadklasse (TIdThread), deren Execute Methode in einer Schleife liegt und deren Ausführung man von aussen leicht anhalten und wieder aufnehmen kann.

TIdThread hat kaum externe Abhängigkeiten und kann daher auch leicht modifiziert ohne Indy verwendet werden.

Funktioniert ab Delphi 5, ich selber nutze sie auch mit Delphi 6 und bisher problemlos.

DeddyH 5. Feb 2012 09:03

AW: Thread: Suspend und Resume deprecated
 
In meinem aktuellen Projekt mache ich das über ein Event.
Delphi-Quellcode:
type
  TMyThread = class(TThread)
  private
    FEvent: THandle;
    ...
  public
    procedure SuspendWork;
    procedure ContinueWork;
    ...
  end;

constructor TMyThread.Create;
begin
  (* Non-Signaled-Event anlegen *)
  FEvent := CreateEvent(nil, true, false, '');
  ...
end;  

procedure TMyThread.ContinueWork;
begin
  (* Event auf Non-Signaled zurücksetzen *)
  ResetEvent(FEvent);
end;

procedure TMyThread.Execute;
begin
  ...
  (* Falls Event Signaled ist, warten *)
  while (WaitForSingleObject(FEvent, 0) = WAIT_OBJECT_0) and
    not Terminated do
    sleep(0);
  if Terminated then
    break;
  ...
end;

procedure TMyThread.SuspendWork;
begin
  (* Event auf Signaled setzen *)
  SetEvent(FEvent);
end;

mjustin 5. Feb 2012 09:25

AW: Thread: Suspend und Resume deprecated
 
Zitat:

Zitat von DeddyH (Beitrag 1149309)
Delphi-Quellcode:
procedure TMyThread.Execute;
begin
  ...
  (* Falls Event Signaled ist, warten *)
  while (WaitForSingleObject(FEvent, 0) = WAIT_OBJECT_0) and
    not Terminated do
    sleep(0);
  if Terminated then
    break;
  ...
end;

Gibt es eine elegantere Lösung als eine Schleife mit Sleep(0)?

Unter http://borland.newsgroups.archived.a...507263541.html werden Sleep(0)-Schleifen als "low-priority-thread-killing, processor-eating" bezeichnet (was ich frei übersetze als "blockiert Threads niedrigerer Priorität, und frisst Prozessorzeit"). (Punkt 5)

himitsu 5. Feb 2012 09:36

AW: Thread: Suspend und Resume deprecated
 
Rate mal, wofür man dort ein TimeOut angeben kann.
WaitFor wartet auf das Event und will man nebenbei noch Eventunabhängig z.B. noch das Terminated prüfen, dann ginge das darüber.

Über das TimeOut hat man quasi ein Sleep, welches regelmäßige Auswertungen erlaubt, den Thread meistens schlafen läßt (CPU-Entlastung) und gleichzeitig dennoch, über das Event, schnell reagieren kann.

Siehe DelayDelay.

Sir Rufo 5. Feb 2012 09:41

AW: Thread: Suspend und Resume deprecated
 
Klar geht das eleganter:
Delphi-Quellcode:
type
  TMyThread = class(TThread)
  private
    FEvent: THandle;
    ...
  public
    destructor Destroy; override;
    procedure Terminate; override;
    procedure SuspendWork;
    procedure ContinueWork;
    ...
  end;

procedure TMyThread.Terminate;
begin
  inherited;
  SetEvent( FEvent );
end;

destructor TMyThread.Destroy;
begin
  if not Terminated then
    begin
      Terminate;
      WaitFor;
    end;
  inherited;
end;

constructor TMyThread.Create;
begin
  (* Signaled-Event anlegen *)
  FEvent := CreateEvent(nil, true, true, '');
  ...
end;

procedure TMyThread.ContinueWork;
begin
  (* Event auf Signaled setzen *)
  SetEvent(FEvent);
end;

procedure TMyThread.Execute;
begin
  while not Terminated do
    begin

      (* Falls Event Non-Signaled ist, warten *)
      if
         ( WaitForSingleObject( FEvent, INFINITE ) = WAIT_OBJECT_0 ) and
         not Terminated
      then
        begin

          // Hier jetzt das rein, was der Thread abarbeiten soll

        end;

    end;
end;

procedure TMyThread.SuspendWork;
begin
  (* Event auf Non-Signaled setzen *)
  ResetEvent(FEvent);
end;

Furtbichler 5. Feb 2012 11:56

AW: Thread: Suspend und Resume deprecated
 
WaitForSingleObject kehrt auch zurück, wenn man das Handle mit CloseHandle schließt, d.h. man muss nicht unbedingt Terminate überschreiben.
Das geht nebenbei bei älteren Delphi-Versionen gar nicht.


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