Entwickler-Ecke

Internet / Netzwerk - DownloadThread stoppt einfach


Hendi48 - Do 23.08.07 18:19
Titel: DownloadThread stoppt einfach
Hi,
ich habe einen DownloadThread:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
unit Thread2;

 
interface  

 
uses Windows, SysUtils, Classes, IdHTTP, IdComponent, SyncObjs;  

 
type  
  TThreadWorkEvent = procedure(Sender: TThread; AWorkMode: TWorkMode; const AWorkCount: Integer)  
   of object;  
  TWorkBeginEvent = procedure(Sender: TObject; AWorkMode: TWorkMode;  
   const AWorkCountMax: Integer) of object;  

type  
  DownloadThread = class(TThread)
  private  
    FIdHTTP: TIdHTTP;  
    FWorkEvent: TThreadWorkEvent;  
    FURL: String;  
    FFileName: String;  
    FWorkCountMax: Integer;  
    procedure InternalOnWork(ASender: TObject; AWorkMode: TWorkMode;
      AWorkCount: Integer);
    procedure InternalOnWorkBegin(ASender: TObject; AWorkMode: TWorkMode;
      AWorkCountMax: Integer);
  protected
    procedure Execute; override;  
  public
    constructor Create;  
    destructor Destroy; override;  
    property URL: String read FURL write FURL;  
    property FileName: String read FFileName write FFileName;  
    property WorkCountMax: Integer read FWorkCountMax;  
    property OnWork: TThreadWorkEvent read FWorkEvent write FWorkEvent;  
  end;  

 
implementation  

constructor DownloadThread.Create;
begin
  inherited Create(True);  
  FIdHTTP := TIdHTTP.Create(nil);
  FIdHTTP.OnWork := InternalOnWork;
  FIdHTTP.OnWorkBegin := InternalOnWorkBegin;
end;  

destructor DownloadThread.Destroy;
begin
  FIdHTTP.Free;  
  inherited;
end;  

procedure DownloadThread.Execute;
var  
  Handle: THandle;  
  FS: TFileStream;  
begin  
  Handle := FileCreate(FileName);
  if Handle <> INVALID_HANDLE_VALUE then  
  begin  
    FS := TFileStream.Create(Handle);  
    try  
      FIdHTTP.Get(FURL, FS);  
    finally  
      FS.Free;  
    end;  
  end;
end;  

procedure DownloadThread.InternalOnWork(ASender: TObject; AWorkMode: TWorkMode;
      AWorkCount: Integer);
begin
  if Assigned(FWorkEvent) then
    FWorkEvent(Self, AWorkMode, AWorkCount);
end;  

procedure DownloadThread.InternalOnWorkBegin(ASender: TObject; AWorkMode: TWorkMode;
      AWorkCountMax: Integer);
begin  
  FWorkCountMax := AWorkCountMax;
end;  

end.

Der funktioniert auch eigentlich, nur manchmal stoppt es einfach mitten im Download.

Der Aufruf ist so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
  Thread2 := DownloadThread.Create;
  with Thread2 do
  begin
    FreeOnTerminate := True;
    OnWork := Self.OnWork;
    URL := 'http://battlefield-basis.de/bf2maps/Kursk.zip';
    FileName := 'test.zip';
    Resume;
  end;

(Thread2: DownloadThread; in private deklariert)
Brauch ich da vielleicht noch ein Synchronize oder so? (sry kenn mich mit Threads nicht wirklich aus)

Edit: aja ich hab noch OnWork (von MainForm) vergessen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TMainForm.OnWork(Sender: TThread; AWorkMode: TWorkMode; const AWorkCount: Integer);
const
  S_MSG = '%d Bytes von %d Bytes gedownloadet.';
begin
  if Sender = Thread2 then
    Label1.Caption := Format(S_MSG, [AWorkCount, (Sender as DownloadThread).WorkCountMax]);
    Progress2.Max := (Sender as DownloadThread).WorkCountMax;
    Progress2.Position := AWorkCount
end;


arj - Fr 24.08.07 08:48

Da du GUI-Darstellungen in deinem Thread änderst MUSST du die Methode Synchronize benutzen,
wie du schon richtig erkannt hast.

Versuch also mal, alles was an der GUI rumschraubt in ne Methode UpdateGUI zu schreiben
und diese dann mit Synchronize(UpdateGUI); aufzurufen.


Hendi48 - Fr 24.08.07 13:45

Aber eigentlich wird doch nur in der MainForm OnWork was am GUI geändert. Soll ich das trotzdem Synchrnisieren?


Narses - Fr 24.08.07 13:54

Moin!

user profile iconHendi48 hat folgendes geschrieben:
Aber eigentlich wird doch nur in der MainForm OnWork was am GUI geändert. Soll ich das trotzdem Synchrnisieren?

Genau das ist der Grund, warum du sychronisieren sollst! :mahn:

cu
Narses


Hendi48 - Fr 24.08.07 14:17

ok, ich hab Mainform.Onwork jetz so umgeändert:

Delphi-Quelltext
1:
2:
  if Sender = Thread2 then
    Synchronize(UpdateGUI);

Ich kuck mal ob es jetzt geht.. :)

Edit: Er hat Fehler beim Compilen: Bei dem Synchronize() meint er Operator oder Semikolon fehlt und woher soll die Update GUI Procedure eigentlich wissen was AWorkCount is und so?


GTA-Place - Fr 24.08.07 14:27

Nimm nicht das OnWork von Form1 sondern deklariere das ganze für den TThread.


Hendi48 - Fr 24.08.07 15:01

ok, danke es scheint jetzt zu funktionieren. Nur die ProgressBar fängt erst nach so 10s an sich zu füllen (ich seh aber das es schon downloadet in cFos Speed). Kann ich noch irgendwie machen das die sofort von Anfang an sich füllt?