Einzelnen Beitrag anzeigen

Stewag

Registriert seit: 12. Jun 2008
175 Beiträge
 
Delphi 12 Athens
 
#11

AW: Einbinden eines Thread Downloads

  Alt 21. Jul 2024, 19:16
Danke jaenicke, aber so einfach ist es nicht.

Es fehlt schon mal der Deklarationsteil und auch der Constructor.

Habe mal versucht, das nach den Angaben von Himitsu zu ergänzen.
So bekomme ich zumindest schon mal keinen Laufzeitfehler:

Code:
unit SyncThreadedDownload;

interface

uses
  System.RTLConsts, System.SysUtils, System.Classes, System.Net.HttpClient, System.Net.URLClient;

type
  TDownloadCompleteEvent = reference to procedure(const URL: String; Stream: TStream; Error: Exception);

  TFileDownloader = class(TThread)
    procedure ThreadedDownloadFile(const URL: String; OnDownloadComplete: TDownloadCompleteEvent);

  private
    FStream: TStream;
    FOnDownloadComplete: TDownloadCompleteEvent;

  public
    constructor Create(const URL: String; OnDownloadComplete: TDownloadCompleteEvent);
    property OnDownloadComplete: TDownloadCompleteEvent read FOnDownloadComplete write FOnDownloadComplete;

  end;

implementation

{ TFileDownloader }
constructor TFileDownloader.Create(const URL: String; OnDownloadComplete: TDownloadCompleteEvent);
begin
  if not Assigned(OnDownloadComplete) then
    raise Exception.Create('peng');
  inherited Create(False); // Himitsu: "und jetzt außen kein Start mehr, da es am Ende des Create von selbst startet" -> Äääh, wie bitte?
  FreeOnTerminate := True;
  FOnDownloadComplete := OnDownloadComplete; // Himitsu: "und der Rest im Execute/DownloadFile" -> ich glaube der Rest steckt jetzt in ThreadedDownloadFile, oder ??? 
end;

procedure TFileDownloader.ThreadedDownloadFile(const URL: String; OnDownloadComplete: TDownloadCompleteEvent);
begin
  if (URL = '') or not Assigned(OnDownloadComplete) then
    raise EArgumentException.CreateRes(@SArgumentNil);
  TThread.CreateAnonymousThread(
    procedure
    var
      HTTP: THTTPClient;
      Stream: TMemorystream;
      DError: Exception;
    begin
      TThread.NameThreadForDebugging('ThreadedDownloadFile');
      DError := nil;
      HTTP := THTTPClient.Create;
      Stream := TMemorystream.Create;
      try
        HTTP.CustomHeaders['Pragma'] := 'no-cache';
        try
          HTTP.Get(URL, Stream);
          { TThread.Synchronize(nil,
            procedure
            begin
            OnDownloadComplete(URL, Stream, nil);
            end); }
        except
          { on E: Exception do begin
            TempErr := E; // durch einen Bug muß es kopiert werden, auch wenn der Compiler sich bei OnDownloadComplete(URL, nil, E); nicht beschwert ... E ist im Sync leider NIL
            TThread.Synchronize(nil,
            procedure
            begin
            //OnDownloadComplete(URL, nil, E); // siehe Bugreport im alten QualityPotal
            OnDownloadComplete(URL, nil, TempErr);
            end);
            end; }
          FreeAndNil(Stream);
          // für das if-Assigned im OnDownloadComplete ... oder einfach lassen, auch wenn es eh nichts sinnvolles enthält, und nur auf Assigned(Error) prüfen
          DError := AcquireExceptionObject as Exception;
        end;
        TThread.Synchronize(nil,
          procedure
          begin
            OnDownloadComplete(URL, Stream, DError);
          end);
      finally
        DError.Free;
        Stream.Free;
        HTTP.Free;
      end;
    end).Start;
end;

end.
Leider klappt aber der Aufruf mit keiner der beiden angegebenen Methoden. Beide mal erhalte ich den Fehler "[dcc32 Fehler] Unit1.pas(43): E2076 Diese Form des Methodenaufrufs ist nur für Klassenmethoden oder Konstruktoren zulässig"

Code:
type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure DownloadComplete(const URL: String; stream: TStream; Error: Exception);

  private
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
  {Methode 1:
  TFileDownloader.ThreadedDownloadFile('https://www.example.de/test',
    procedure(const URL: String; stream: TStream; Error: Exception)
    begin
      if Assigned(stream) then
      begin // if not Assigned(Error) then
        begin
          Memo1.lines.LoadFromStream(stream);
          ShowMessage('Download complete: ' + URL);
        end;
      end;
    end);
    }
// Methode 2
   TFileDownloader.ThreadedDownloadFile('https://www.example.de/test', DownloadComplete);
end;

procedure TForm1.DownloadComplete(const URL: String; stream: TStream; Error: Exception);
begin

//Wie kann ich hier abfragen, ob eine Exception vorliegt?

    Memo1.lines.LoadFromStream(stream)
  // else
  // Label1.Text := 'Download failed';
end;
Steffen

Geändert von Stewag (21. Jul 2024 um 19:18 Uhr)
  Mit Zitat antworten Zitat