Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#8

AW: Einbinden eines Thread Downloads

  Alt 19. Jul 2024, 19:24
Es gibt Fremd-Bibliotheken, die sowas drin haben.
Das Ganze kann man ja noch mit vielen Dingen erweitern und somit nicht allen Recht machen ... den Einen isses zuviel und Anderen fehlt immer irgendwas.
* z.B. ein Pooling, damit man 200 Dateien downloaden kann, aber nicht zu viele Threads gleichzeitig laufen.
* schönere Fehlernehandlung
* Proxy
* uvm.
Je nach Anforderung muß man sich dann was Passendes suchen.


Es gibt verschiedene Arten von Prozeduren/Methoden
und genauso gibt es verschiedene Arten von MethodenZeigern, welche Referenzen auf diese Methoden aufnehmen können.
Delphi-Quellcode:
type
  TEvent1 = reference to procedure(const URL: String; Stream: TStream; Error: Exception); // Proc1, Proc2, Proc3, Proc4 und Inline5
  TEvent2 = procedure(const URL: String; Stream: TStream; Error: Exception) of object; // Proc2, Proc3
  TEvent3 = procedure(const URL: String; Stream: TStream; Error: Exception); // Proc1 (glaub auch Proc4)

// Prozedur
procedure Proc1(const URL: String; Stream: TStream; Error: Exception);

type
  TDemo = class

    // Methode
    procedure Proc2(const URL: String; Stream: TStream; Error: Exception);

    // KlassenMethode
    class procedure Proc3(const URL: String; Stream: TStream; Error: Exception);

    // statische KlassenMethode
    class procedure Proc4(const URL: String; Stream: TStream; Error: Exception); static;

  end;

// anonyme Methode, also "Inline5" im Code
begin
  eineVariable := procedure(const URL: String; Stream: TStream; Error: Exception)
    begin
    end;

  AlsParameter(procedure(const URL: String; Stream: TStream; Error: Exception)
    begin
    end);
end;

// eingebettete Prozedur
procedure {TDemo.}Test;
  procedure Proc6(const URL: String; Stream: TStream; Error: Exception);
  begin
  end;
begin
  Proc6(…);
end;





Freigeben muß man den Thread ja nicht selbst, denn durch das FreeOnTerminate gibt er sich selbst frei.
Weil man extern nicht weiß wann, darf extern grundsätzlich niemals "ungeschützt" auf eine Variable zugegriffen werden, welche auf diesen Thread zeigt.
Extern garkeine Variable, mit dem Objektzeiger, und schon kommt auch niemand auf dumme Ideen.

Ohne FreeOnTerminate könnte man extern z.B. auf Thread.Terminated prüfen
und anschließend selbst den den Thread freigeben, bzw. vorher z.B. die runtergeladenen Daten von ihm abholen.

Man kann selbst TThread ableiten
und seinen Code ins Execute einfügen, sowie eventuell auch ins Create.

Im Prnzip gibt es aber bereits eine fertige Ableitung des TThread,
die eine Prozedur bekommt, welche sie dann im Thread ausführt.
Delphi-Referenz durchsuchenTThread.CreateAnonymousThread

Delphi-Quellcode:
type
  TAnonymousThread = class(TThread)
  private
    FProc: TProc;
  protected
    procedure Execute; override;
  public
    constructor Create(const AProc: TProc);
  end;

class function TThread.CreateAnonymousThread(const ThreadProc: TProc): TThread;
begin
  Result := TAnonymousThread.Create(ThreadProc);
end;

constructor TAnonymousThread.Create(const AProc: TProc);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  FProc := AProc;
end;

procedure TAnonymousThread.Execute;
begin
  FProc();
end;
Also anstatt einer eigenen TThread-Klasse, hatte ich einfach nur dieses Fertige benutzt.
  • Die Aktionen zum Erstellen kann man ja vor oder im Create erledigen.
  • Und das für's Execute wurde hier einfach als Methode/Event reingegeben, anstatt es direkt reinzuschreiben.

Ohne den auskommentierten Code, für eine alternative Behandlung, ist es hier recht kurz gehalten (passt alles komplett auf den Bildschirm),
und durch die anonymen (eingebetteten) Methoden liegt hier der Code funktional übersichtlich in seiner Ablaufreihenfolge.
Aber grundsätzlich ist es auch kein Problem Vieles in externe Methoden auszulagern, aber dann am Besten schön in einer Klasse gekapselt.

Bei dem eingebetteten Synchronize kann man es auch ausnutzen, dass sich Variablen "automatisch" vom Übergeordneten Code dort reingeben lässt.
(Delphi verschiebt diese Variablen "heimlich" in ein Interface, mit Referenzzähung ... bis der aufrufende Code und der Eingebetette alle beendet wurden)
$2B or not $2B

Geändert von himitsu (19. Jul 2024 um 19:40 Uhr)
  Mit Zitat antworten Zitat