Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Threads nacheinander ausführen (https://www.delphipraxis.net/128570-threads-nacheinander-ausfuehren.html)

TheMiller 1. Feb 2009 22:01


Threads nacheinander ausführen
 
Hallo,

arbeite mal wieder ein bissl mit Threads. Möchte Downloads von Dateien durchführen. Diese Daten sollen nacheinander geladen werden und nicht parallel. Momentan werden die Threads gleichzeitig gestartet und demnach laufen sie auch parallel. Hier mal mein Code:

(Dies ist ein Auszug aus meiner "Updater-Unit")

Delphi-Quellcode:
  TDownloadUpdate = class(TThread)
  private
    fFile: String;
    fUrl: String;
    fParent: HWND;
    procedure SetFile(Value: String);
    procedure SetUrl(Value: String);
  public
    Done: Boolean;
    constructor Create;
  protected
    procedure Execute; override;
  published
    property File2Load:String read fFile write SetFile;
    property Url: String read fUrl write SetUrl;
  end;

procedure TDownloadUpdate.Execute;
var
  www: TIdHttp;
  fs: TFileStream;
begin
  inherited;
  www:=TIdHttp.Create(nil);
  [url]www.Port:=81;[/url] // Nur testweise, da Apache auf 81 lauscht.
  try
    try
      ForceDirectories(ExtractFilePath(ParamStr(0))+'\Updates\');
      fs:=TFileStream.Create(ExtractFilePath(ParamStr(0))+'Updates\'+fFile, fmCreate);
      www.Get(fUrl, fs);
    except
      //
    end;
  finally
    [url]www.free;[/url]
    fs.Free;
  end;
end;

procedure TUpdater.DownloadUpdate(i: Integer);
var
  du: TDownloadUpdate;
begin
  du:=TDownloadUpdate.Create();
  with (du) do
  begin
    FreeOnTerminate:=True;
    SetFile(GetUpdateInfo(i, 'filename'));
    SetUrl(GetUpdateInfo(i, 'url'));
    Resume;
  end;
end;
(hier die Hauptanwendung)

Delphi-Quellcode:
procedure TForm1.StartUp;
begin
  Updater:=TUpdater.Create;
  Updater.SeekUpdates('http://127.0.0.1/test/updates.ini', Self.Handle);
end;

procedure TForm1.PngBitBtn2Click(Sender: TObject);
begin
  Updater.DownloadUpdate(0);
  Updater.DownloadUpdate(1);
end;
Vielen Dank im Voraus!

Die Muhkuh 1. Feb 2009 22:04

Re: Threads nacheinander ausführen
 
Wenn es nacheinander sein soll, brauchst eigentlich keine Threads oder nur einen

TheMiller 1. Feb 2009 22:09

Re: Threads nacheinander ausführen
 
Das verstehe ich nicht ganz. Ich lager das in Threads nur aus, damit das Programm nicht einfriert und ich kein Application.ProcessMessages verwenden muss.

Mehrere Threads habe ich, damit ich auch einzelne Dateien (und nicht alle) runterladen muss. Weiterhin möchte ich pro Datei Downloadstatus und weitere Infos anzeigen.

Die Muhkuh 1. Feb 2009 22:12

Re: Threads nacheinander ausführen
 
Würde es nicht reichen, einem Thread alle Dateien, die runtergeladen werden sollen, zu übergeben und der diese nacheinander runterlädt?

dominikkv 1. Feb 2009 22:21

Re: Threads nacheinander ausführen
 
Delphi-Quellcode:
function MyWaitFor(Event: THandle): Boolean; // von negaH: [url]http://www.delphipraxis.net/post696510.html#696510[/url]
begin
  Result := False;
  while not Result do
    case MsgWaitForMultipleObjects(1, Event, False, INFINITE, QS_ALLINPUT) of
      WAIT_OBJECT_0:
        Result := True;
      WAIT_OBJECT_0 + 1:
        begin
          Application.ProcessMessages;
          if Application.Terminated then Exit;
        end;
    else
      RaiseLastWin32Error;
    end;
end;

constructor TDownloadUpdate.Create(aFilename, aURL: string; aFinishEvent: Cardinal);
begin
  inherited Create(True);
  fFile := aFilename;
  fUrl := aURL;
  fFinishEvent := aFinishEvent;
  FreeOnTerminate := True;
  resume;
end;

procedure TDownloadUpdate.Execute;
var
  www: TIdHttp;
  fs: TFileStream;
begin
  inherited;
  www:=TIdHttp.Create(nil);
  [url]www.Port:=81;[/url] // Nur testweise, da Apache auf 81 lauscht.
  try
    try
      ForceDirectories(ExtractFilePath(ParamStr(0))+'\Updates\');
      fs:=TFileStream.Create(ExtractFilePath(ParamStr(0))+'Updates\'+fFile, fmCreate);
      www.Get(fUrl, fs);
    except
      //
    end;
  finally
    [url]www.free;[/url]
    fs.Free;
    SetEvent(fFinishEvent);
  end;
end;

procedure TUpdater.DownloadUpdate(i: Integer);
var
  Event: THandle;
begin
  Event := CreateEvent(nil, False, False, 'ThreadFinished');
  TDownloadUpdate.Create(GetUpdateInfo(i, 'filename'), GetUpdateInfo(i, 'url'), Event);
  MyWaitFor(Event);
  CloseHandle(Event);
end;

TheMiller 1. Feb 2009 22:22

Re: Threads nacheinander ausführen
 
Hm.. das wäre sicherlich eine gute Alternative. Würde sich in meinem Projekt auch realisieren lassen. Aber ich würde trotzdem gerne wissen, wie ich Threads nacheinander laufen lassen kann. Einfach auch Interesse.

Roter Kasten: Ok, super ;) Werde ich dann auch mal ausprobieren. Danke!

Luckie 1. Feb 2009 22:27

Re: Threads nacheinander ausführen
 
Man könnte mit MSDN-Library durchsuchenWaitForSingleObject auf die Beendigung eines Threads warten und dann den nächsten starten.

alzaimar 2. Feb 2009 06:39

Re: Threads nacheinander ausführen
 
Ich würde das straight-forward machen, genauso wie Du es willst:

Threads nacheinander ausführen = Thread Nr.X startet Thread Nr.(X+1)

Du erstellst Dir eine Liste aller Threads und sorgst dafür, das ein Thread beim Beenden (OnTerminate) den nächsten Thread aktiviert.
Delphi-Quellcode:
Var
  MyThreadList : TList; // Of Threads
  CurrentThread : TMyThread;

Procedure TMainForm.RunNextThread (Sender : TObject);
Begin
  If MyThreadList.Count>0 Then Begin            // Wenn noch Threads abzuarbeiten sind,
    CurrentThread := TMyThread(MyThreadList[0]); // nimm den nächsten,
    MyThreadList.Delete(0);                     // entferne ihn aus der Liste
    CurrentThread.Resume;                       // und führe ihn aus
  End
  Else Begin
    ShowMessage('Alle Threads wurden ausgeführt');
    FreeAndNil (MyThreadList);  
  End;
End;
   
Procedure TMainForm.ExecuteAllThreads;
Var
  i : Integer;
  myThread : TMyThread;

Begin
{$IFDEF AllowAddingOfThreadsWhileExecuting}
  If Assigned (MyThreadList) Then
    Raise Exception.Create('Es sind noch nicht alle Threads abgearbeitet');
{$ELSE}
  If Not Assigned (MyThreadList) Then
    MyThreadList := TList.Create;
{$ENDIF}
  For i:=0 to MyThreadCount do Begin
    myThread := TMyThread.Create (...); // Suspended muss TRUE sein.
    myThread.OnTerminate := RunNextThread;
    myThread.FreeOnTerminate := True;  // Kannst du so machen oder nicht.
    MyThreadList.Add(myThread);
  End;
  RunNextThread(nil);
End;
So kannst Du dir das 'warten auf den nächsten Thread' sparen. Die Variable 'CurrentThread' benötigst Du, wenn Du die Anwendung beenden willst, und noch nicht alle Threads abgearbeitet sind. Dann Terminierst Du den 'CurrentThread' und löschst einfach die MyThreadList.

TheMiller 2. Feb 2009 07:43

Re: Threads nacheinander ausführen
 
Morgen!

@alzaimar: Genau so habe ich es gemacht, doch das Event OnTerminate wurde nie ausgeführt. Und, btw, wenn den Ihnalt der Execute-Funktion in eine andere Funktion auslagere (zB Download) und diese im Execute mit Synchronize aufrufe, dann wird diese garnicht gestartet. Vielleicht hängt das irgendwie zusammen.

himitsu 2. Feb 2009 08:18

Re: Threads nacheinander ausführen
 
Zitat:

Zitat von alzaimar
Ich würde das straight-forward machen, genauso wie Du es willst:

Threads nacheinander ausführen = Thread Nr.X startet Thread Nr.(X+1)

wieso denn nicht eine Liste aller zu ladender Dateien EINEM Thread geben, welcher diese Liste dann selber nacheinander abarbeitet?


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:09 Uhr.
Seite 1 von 2  1 2      

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