Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Ist es möglich über TParallel eine Procedure zum ausführen zu übergeben? (https://www.delphipraxis.net/195884-ist-es-moeglich-ueber-tparallel-eine-procedure-zum-ausfuehren-zu-uebergeben.html)

Kostas 3. Apr 2018 22:47

Delphi-Version: 10.2 Tokyo

Ist es möglich über TParallel eine Procedure zum ausführen zu übergeben?
 
Hallo Zusammen,

es geht um ein Android Projekt welches sich an einem DataSnap Server verbindet. Die Verbindung ist nicht stabil weil es eben ein mobiles Gerät ist.
Der Server stellen einige Methoden bereit. Ich hätte gerne einen Thread dem ich die Methode z.B.: GetAdress(PersonID) übergebe. Der Thread feuert zunächst die GetAdress. Wenn es knallt, baut er die Verbindung auf und feuer GetAdress erneut.


Gibt es eine Möglichkeit über die neue TParallel Klassen das umzusetzen?
Nach was müsste ich bitte suchen, ich finde sehr wenig Dokumentation zu dem Thema?
Ich habe die Beispiel zu TTask.Run, TTask.Future und TParallel.For angeschaut dann gibt es noch ein Join aber viel mehr konnte ich noch nicht finden.

Gruß Kostas

himitsu 4. Apr 2018 01:41

AW: Ist es möglich über TParallel eine Procedure zum ausführen zu übergeben?
 
TParallel ist dafür gut mehrere "zusätzliche" Threads zu verwalten -> Eine Aufgabe automatisch auf viele Threads verteilen.

Du willst nur "einen" Thread haben, da wäre TThread oder eben moderner TTask eines der Mittel deiner Wahl.
http://docwiki.embarcadero.com/RADSt...amming_Library


Alternativ nur ein/einige ständig laufende(r) Thread(s), dem/denen du z.B. über eine Liste Aufgaben übergibst, die nacheinander da rausgeholt und abgearbeitet werden.
Im Prinzip übernimmt das TTask für dich.

Kostas 4. Apr 2018 08:00

AW: Ist es möglich über TParallel eine Procedure zum ausführen zu übergeben?
 
Hi himitsi,
Meine Auflistung der Beispiele kommen zufällig aus ganau deinem Link. Die habe ich also alle abgearbeitet. So wie dich einschätze hast du mir schon die richtigen Tipp gegeben mit: Ein Thread der eine Queue abarbeiten kann. Demnach ist TParallels dafür nicht geeignet. Das "normale" Zeug mit TThread ist richtig kompliziert. Kennst du zufällig ein Beispiel in dem gezeigt wird wie ein Thread als Parameter eine Prozedur übergeben bekommt die ebenfalls Paramerer enthält?. Alle Beispiele die ich gefunden habe sind mit Anonyme Methoden ohne Parameter. Ich würde gerne dem Thread die Methode z.B.: GetAdress (adressID) zum ausführen
übergeben.

Gruß Kostas

himitsu 4. Apr 2018 09:11

AW: Ist es möglich über TParallel eine Procedure zum ausführen zu übergeben?
 
Eine der "billigsten" Varianten mit TThread wäre z.B.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  S: string;
begin
  Button1.Caption := '...';
  S := 'A B C';
  TThread.CreateAnonymousThread(procedure
    begin
      Sleep(3000);
      S := ReverseString(S);
      //...
      TThread.Synchronize(nil, procedure
        begin
          Button1.Caption := S;
        end);
    end).Start;
end;
Aber das Erstellen/Starten eines Thread verbraucht einiges an Systemressourcen (ist langsam).

Mit TTask kann man das ähnlich machen.
Aber dort kann man einen eigenen ThreadPool angeben oder den globalen ThreadPool nutzen, wobei diese Threads wiederverwendet und nicht immer neu erstellt werden.
Auch kann man die maximale Anzahl gleichzeitiger Tasks steuern und es gibt NotifyEvents, wenn einer/alle Tasks fertig sind und das Teil kann noch viel mehr.

TTask, TFuture, TParallel usw. bassieren aud TThread und erweitern es um weitere Features, die du dann nicht selber implementieren mußt, vor allem in Bezug auf eine bessere Verwaltung der Thread-Ressourcen.
TFeature ist ein TTask mit "tu was" und zusätzlich einem Delphi-Referenz durchsuchenTFeature.GetValue (gib mit das Ergebnis und warte notfalls, falls noch nicht fertig).

Du kannst z.B. selber eine ArbeitsListe für einen/mehrere Threads verwalten.
Delphi-Quellcode:
var
  List: TThreadList<string>;

procedure TDeinWorkerThread.Execute;
var
  LockedList: TList<string>;
  Value: string;
begin
  while not Terminated do begin
    Value := '';
    LockedList := List.LockList;
    try
      if LockedList.Count > 0 then begin
        Value := LockedList[0];
        LockedList.Delete(0);
      end;
    finally
      List.UnlockList;
    end;
    if Value <> '' then begin
      Sleep(3000);
      Value := ReverseString(Value);
      //...
      Synchronize(procedure
        begin
          Form10.Button1.Caption := Value;
        end);
    end else
      Sleep(100);
  end;
end;
Und dann fänst du auch noch an die Behandlung zu optimieren usw.

Oder eben die TTask oder TFeature, wo dafür schon Einiges eingebaut ist.

Kostas 4. Apr 2018 12:40

AW: Ist es möglich über TParallel eine Procedure zum ausführen zu übergeben?
 
Hallo himitsu,

mal sehen ob ich dich richtig verstanden habe. In beiden deiner Beispiele ist die Methode innerhalb des Threads verankert und wird ausgeführt. Daraus entnehme ich, es ist nicht möglich die Methode ReverseString(s) dem Thread zu übergeben. Für mein Projekt bedeutet das, wenn wir bei CreateAnonymousThread bleiben wollen, ich müsste jede Methode die der DataSnap Server bereitstellt umkapseln mit dem CreateAnonymousThread?

Also etwa so:


//Jede DataSnap Methode muss ich also so verpacken. Ich kann die DataSnap Methode einem Thread nicht übergeben!
Delphi-Quellcode:
procedure GetAdress_ViaThread(const AdressID: integer);
begin
  TThread.CreateAnonymousThread(procedure
    begin
      CheckDataSnapConnection;
       
      if FutureDSConneced.value //Thread wird blockiert bis Antwort kommt. FutureDSConneced ist eine globale public Variable vom Typ FutureDSConneced: IFuture<boolean>;
      then GetAdress(AdressID);
    end).Start;
end;
Delphi-Quellcode:
procedure TForm1.CheckDataSnapConnection;
begin
  FutureDSConneced := TTask.Future<boolean>(
    function:boolean
    begin
      result := false;
     
      try
        dm1.DSRestConnection1.TestConnection();
        result := true;
//        dm1.DSRestConnection1.Reset;

      except
        on E: Exception do
        begin
          HandleException(E);
        end;

      end;
    end);
end;

Gruß Kostas

Kostas 5. Apr 2018 16:33

AW: Ist es möglich über TParallel eine Procedure zum ausführen zu übergeben?
 
Hallo himitsu,

über diesen Ansatz versuche ich gerade TThreadProcedure in eine TQueue zu schreiben mit der Absicht, dass die Proceduren sequenziell ausgeführt werden können.
Doch die Proceduren werden nicht ausgeführt. Kannst du erkennen warum?



Delphi-Quellcode:

  private
    { Private-Deklarationen }
    var ProcQuere: TQueue<TThreadProcedure>;
    procedure ExecuteQueue;
    procedure Methode1InQueue;
    procedure Methode2InQueue;
  public
    { Public-Deklarationen }
  end;

 
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  ProcQuere := TQueue<TThreadProcedure>.Create;
  ExecuteQueue;
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  ProcQuere.Clear;
  ProcQuere.Free;
end;

procedure TForm1.btMethode1Click(Sender: TObject);
begin
  Methode1InQueue;
end;

procedure TForm1.btMethode2Click(Sender: TObject);
begin
  Methode2InQueue;
end;


procedure TForm1.ExecuteQueue;
begin
  TThread.CreateAnonymousThread(procedure
  var proc: TThreadProcedure;
  begin
    while not Application.Terminated do begin //Endlosschleife bis App beendet wird
      if ProcQuere.Count <> 0 then
      begin
        proc := ProcQuere.Dequeue();
        proc();
      end;
    end;
  end).Start;

end;
 
procedure TForm1.Methode1InQueue;
begin
  ProcQuere.Enqueue(procedure
    begin
      TThread.Synchronize(TThread.CurrentThread,
        procedure
        begin
          mo1.Lines.Add('Methode1InQueue');
        end);
    end);

end;

procedure TForm1.Methode2InQueue;
begin
  ProcQuere.Enqueue(procedure
    begin
      TThread.Synchronize(TThread.CurrentThread,
        procedure
        begin
          mo1.Lines.Add('Methode2InQueue');
        end);
    end);

end;

Gruß Kostas

Kostas 6. Apr 2018 13:13

AW: Ist es möglich über TParallel eine Procedure zum ausführen zu übergeben?
 
HALT hat sich erledigt.

Die Methode muss natürlich manuell ausgeführt werden.


Delphi-Quellcode:
procedure TForm1.ExecuteQueue;
begin
  TThread.CreateAnonymousThread(procedure
  var proc: TThreadProcedure;
  begin
    while not Application.Terminated do begin //Endlosschleife bis App beendet wird
      if ProcQuere.Count <> 0 then
      begin
        proc := ProcQuere.Dequeue();
        proc(); // Die Methode muss natürlich manuell ausgeführt werden.
      end;
    end;
  end).Start;

end;


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