Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Threads anhalten und fortsetzen (https://www.delphipraxis.net/185625-threads-anhalten-und-fortsetzen.html)

SyntaxXx 25. Jun 2015 10:38

Threads anhalten und fortsetzen
 
Hallo zusammen,
mittlerweile habe ich ein gewissen Grundverständnis mit dem Umgang von Threads.

Jetzt würde ich gerne noch mehr wissen.
Wenn ich z.B. 5 WorkerThreads habe, wie halte ich alle an und starte sie später wieder?
Thread.Suspend und Thread.Resume sind ja deprecated und sollen nicht mehr benutzt werden.

Ich habe gelesen, dass man das mit TEvent oder TMutex machen kann.
Allerdings habe ich bis jetzt kein verständliches Beispiel gefunden.


Und wie könnte ich zum Beispiel einzelne Threads anhalten.
Dazu bräuchte ich ja eigentlich eine Liste mit allen Threads, worüber ich einzelne aussuchen kann.
oder wie macht man das?


Vielen Dank schon mal für eure Zeit.

Mavarik 25. Jun 2015 10:42

AW: Threads anhalten und fortsetzen
 
42!

Warum willst Du den einen Thread anhalten?
Oder soll der "nur" warten bis er die nächste Aufgabe bekommt?

Mavarik

BUG 25. Jun 2015 10:54

AW: Threads anhalten und fortsetzen
 
Anhalten kannst du im Regelfall, indem du auf etwas wartest.

Ein spannendes Synchronisationsmittel für dein Problem ist die Condition-Variable, insbesondere wenn du deine geteilten Daten/Aufgaben mit einer CriticalSection schützt.
Ansonsten sehen die auto-reset Events doch auch ganz passend aus.

Eine Liste der verfügbaren Threads zu verwalten wäre in der Tat nicht schlecht :mrgreen:

himitsu 25. Jun 2015 11:08

AW: Threads anhalten und fortsetzen
 
Threads hält man nicht an und vorallem niemals von Außen.

Wenn, dann hält der Thread sich selber an. (er ruft selber z.B. Suspend auf)
Oder er ruft einen wartebefehl auf. (am Meisten wird dafür ein Event verwendes, mit einem WaitFor)

stahli 25. Jun 2015 11:56

AW: Threads anhalten und fortsetzen
 
Der Beitrag vom Sir hat mich kürzlich auf die Spur gebracht: http://www.delphipraxis.net/1268589-post8.html

Danke an der Stelle. :thumb:

Sir Rufo 25. Jun 2015 12:06

AW: Threads anhalten und fortsetzen
 
Hier mal ein kleiner Worker-Thread (ohne viel Gedöns), den man auch schlafen legen kann.
Delphi-Quellcode:
unit Unit2;

interface

uses
  Classes, SyncObjs, SysUtils, Generics.Collections;

type
  TWorkerThread = class( TThread )
  private
    FLockObj: TObject;
    FIsSleeping: Boolean;
    FWorkEvent: TEvent;
    FWorkQueue: TQueue<TProc>;
  protected
    procedure Execute; override;
    procedure TerminatedSet; override;
  public
    constructor Create( CreateSuspended: Boolean );
    destructor Destroy; override;

    /// <summary>
    /// Arbeit an die WorkerThread-Queue übergeben
    /// </summary>
    procedure PushWork( AWorkProc: TProc );

    /// <summary>
    /// WorkerThread schlafen legen
    /// </summary>
    procedure GoSleeping( );
    /// <summary>
    /// WorkerThread wieder aufwecken
    /// </summary>
    procedure Awake( );
  end;

implementation

{ TWorkerThread }

procedure TWorkerThread.Awake;
begin
  TMonitor.Enter( FLockObj );
  try
    FIsSleeping := False;
    if FWorkQueue.Count > 0 then
      FWorkEvent.SetEvent( );
  finally
    TMonitor.Exit( FLockObj );
  end;
end;

constructor TWorkerThread.Create( CreateSuspended: Boolean );
begin
  FLockObj := TObject.Create( );
  FWorkEvent := TEvent.Create( nil, True, False, '' );
  FWorkQueue := TQueue<TProc>.Create( );

  inherited;
end;

destructor TWorkerThread.Destroy;
begin
  inherited;

  FreeAndNil( FLockObj );
  FreeAndNil( FWorkQueue );
  FreeAndNil( FWorkEvent );
end;

procedure TWorkerThread.Execute;
var
  LWorkProc: TProc;
begin
  inherited;
  while not Terminated do
  begin
    if ( FWorkEvent.WaitFor( ) = wrSignaled ) then
      if not Terminated then
      begin

        // Arbeit aus der Queue holen

        TMonitor.Enter( FLockObj );
        try
          LWorkProc := FWorkQueue.Dequeue( );
          if FWorkQueue.Count = 0 then
            FWorkEvent.ResetEvent( );
        finally
          TMonitor.Exit( FLockObj );
        end;

        // Arbeit erledigen

        LWorkProc( );
      end;
  end;
end;

procedure TWorkerThread.GoSleeping;
begin
  TMonitor.Enter( FLockObj );
  try
    FIsSleeping := True;
    FWorkEvent.ResetEvent( );
  finally
    TMonitor.Exit( FLockObj );
  end;
end;

procedure TWorkerThread.PushWork( AWorkProc: TProc );
begin
  TMonitor.Enter( FLockObj );
  try
    FWorkQueue.Enqueue( AWorkProc );
    if not FIsSleeping then
      FWorkEvent.SetEvent( );
  finally
    TMonitor.Exit( FLockObj );
  end;
end;

procedure TWorkerThread.TerminatedSet;
begin
  inherited;
  FWorkEvent.SetEvent( );
end;

end.


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