![]() |
Dateidownload
Hallo zusammen,
wieder mal habe ich ein (vermutlich) kleines Problem. Ich habe mir ein kleines Update-Programm geschrieben, was aus dem Netz eine Datei auf den PC kopiert. Das Funktioniert auch soweit prima, allerdings wollte ich den Bediener per verschiedene Panel davon unterrichten, was er gerade macht. Beispiel: Panel1: "Es steht eine neue Version zur Verfügung." Panel2: "Der Download wurde gestartet, bitte warten!" Panel3: "Der Download wurde abgeschlossen." Diese Panel blende ich per 'visible' und 'true' oder 'false' entweder ein oder aus - zumindest wollte ich das. Panel1 wird mit dem Start des Programms eingeblendet. Klicke ich auf "weiter" (btn_weiter), wird mir zwar das Panel1 ausgeblendet aber nicht das Panel2 eingeblendet. Dies geschieht erst nachdem die Datei runter geladen wurde. Geprüft habe ich es, indem ich "Panel3.Visible := True;" raus genommen habe. Nun die Frage: Warum wird Panel2 erst nachdem ich den Download-Befehl gegeben habe eingeblendet? Das Panel1 wird korrekt ausgeblendet. Hier mein Quelltext:
Delphi-Quellcode:
procedure DeleteIECache;
var lpEntryInfo: PInternetCacheEntryInfo; hCacheDir: LongWord; dwEntrySize: LongWord; begin dwEntrySize := 0; FindFirstUrlCacheEntry(nil, TInternetCacheEntryInfo(nil^), dwEntrySize); GetMem(lpEntryInfo, dwEntrySize); if dwEntrySize > 0 then lpEntryInfo^.dwStructSize := dwEntrySize; hCacheDir := FindFirstUrlCacheEntry(nil, lpEntryInfo^, dwEntrySize); if hCacheDir <> 0 then begin repeat DeleteUrlCacheEntry(lpEntryInfo^.lpszSourceUrlName); FreeMem(lpEntryInfo, dwEntrySize); dwEntrySize := 0; FindNextUrlCacheEntry(hCacheDir, TInternetCacheEntryInfo(nil^), dwEntrySize); GetMem(lpEntryInfo, dwEntrySize); if dwEntrySize > 0 then lpEntryInfo^.dwStructSize := dwEntrySize; until not FindNextUrlCacheEntry(hCacheDir, lpEntryInfo^, dwEntrySize); end; FreeMem(lpEntryInfo, dwEntrySize); FindCloseUrlCache(hCacheDir); end;
Delphi-Quellcode:
Habt Ihr eine Idee? Vielen Dank schon einmal!
procedure TForm1.btn_weiterClick(Sender: TObject);
var quelldatei : String; //-- Quellpfad im Web zieldatei : String; //-- Zielpfand auf Rechner begin Panel2.Visible := True; Panel1.Visible := False; quelldatei := 'http://www.irgendeine-seite.de/dateiname.typ'; zieldatei := 'c:\Programme\mein Programm\dateiname.typ'; DeleteIECache; //-- Cache leeren damit Datei auch tatsächlich aus dem Web geladen wird UrlDownloadToFile(nil, PChar(quelldatei), PChar(zieldatei), 0, nil); //Panel3.Visible := True; Panel2.Visible := False; btn_weiter.Visible := False; btn_fertig.Visible := True; end; LG DieFliege |
AW: Dateidownload
Du könntest zum Testen ein
Delphi-Quellcode:
hinter
Application.ProcessMessages;
Delphi-Quellcode:
einbauen.
Panel1.Visible := False;
Aber das ist wie gesagt nur ein Test. Schöner wäre es, wenn du die Methode
Delphi-Quellcode:
in einen eigenen Thread auslagerst. Ich vermute einfach mal, dass das noch nicht passiert ist. So wie es jetzt ist, wird deine GUI während des Downloads nicht korrekt neu gezeichnet da sie ja mit dem Herunterladen der Datei beschäftigt ist.
UrlDownloadToFile()
|
AW: Dateidownload
Hallo Aviator,
vielen Dank für Deine Antwort. Es hat tatsächlich schon mit "Application.ProcessMessages;" geholfen und Du hast natürlich recht, das Programm wartet solange bis der Download abgeschlossen ist. Natürlich bin ich daran interessiert, wie es funktioniert, wenn man den Download in einen Thread auslagert. Werde dazu mal auf die Suche gehen, wie man dies bewerkstelligt. Vielen Dank erst mal! LG DieFliege |
AW: Dateidownload
Und anstelle mehrere Panels ein und auszublenden solltest Du nur eines verwenden und dessen Beschriftung ändern!
Ciao Stefan |
AW: Dateidownload
Hier hast du eine vernünftige Lösung
Stackoverflow: ![]() Das https kannst du ignorieren es geht hier nur ums Prinzip wie man mit IdHTTP und Work, Workbegin und WorkEnd arbeitet. |
AW: Dateidownload
Hallöle...:P
Zitat:
Hinweis für TE: Das löst aber nicht das Auslagern in einen Thread Problem... |
AW: Dateidownload
Zitat:
|
AW: Dateidownload
So meinte ich das nicht. :P Er hat ja noch keinen Thread. Deshalb muß er immer noch auf Application.ProcessMessages ausweichen. :zwinker: Soll heißen... auch mit den Indys ist der Download blockierend.
|
AW: Dateidownload
Vielleicht so?
Benötigt: ![]()
Delphi-Quellcode:
Deine Prozedur DeleteIECache kannst du löschen. Es gibt schon etwas Fertiges. Einfach Winapi.WinInet.DeleteUrlCacheEntry(filename) aufrufen.
// Variablen
updateThread: TUpdateThread HTTPFileDownload: THTTPFileDownload; procedure IdHTTPProgressOnChange(Sender: TObject); // Initialisierung updateThread := nil; // Im Buttonclick if updateThread = nil then updateThread := TUpdateThread.Create; // Thread-Konstrukt type TUpdateThread = class(TThread) protected procedure Execute; override; public constructor Create; destructor Destroy; override; end; constructor TUpdateThread.Create; begin inherited Create(False); end; destructor TUpdateThread.Destroy; begin inherited Destroy; end; procedure TUpdateThread.Execute; begin // Downloade Datei und und und... Form1.HTTPFileDownload := THTTPFileDownload.Create(nil); Form1.HTTPFileDownload.OnChange := Form1.IdHTTPProgressOnChange; try if Form1.HTTPFileDownload.DownloadFile(sURL, sDestinationOnDisk) then begin // Datei heruntergeladen end else begin // Fehler behandeln end; finally Form1.HTTPFileDownload.Free; end; // Progress procedure TForm1.IdHTTPProgressOnChange(Sender: TObject); var sTmp: string; iDownloaded: Int64; iPercent: Integer; begin iPercent := THTTPFileDownload(Sender).Progress; iDownloaded := HTTPFileDownload.BytesTransfered div 1024; if iPercent = 100 then Exit; if (iPercent mod 5 = 0) then begin Sleep(1); // sTmp := // string zusammenbasteln aus u.a. // iPercent, iDownloaded // Beispielausgabe mit entsprechenden Anpassungen im Execute-Teil, bei mehreren Dateien: // File 6/12: Downloading (91% | 964 KB/1061 KB) end; end; |
AW: Dateidownload
Zitat:
Delphi-Quellcode:
...ohne Synchronisierung auf die Form Variable im Thread zugreifen ist ein No-Go. Wieso soll der Thread die Form kennen? :gruebel:
procedure TUpdateThread.Execute;
begin // Downloade Datei und und und... Form1.HTTPFileDownload := THTTPFileDownload.Create(nil); Form1.HTTPFileDownload.OnChange := Form1.IdHTTPProgressOnChange; ... |
AW: Dateidownload
Ist jetzt einfach abgetippt. Verwende ich schon seit etlichen Jahren so und bisher hat sich niemand beschwert (von XP bis Windows 10).
Ich greife doch nicht auf irgendeine VCL-Komponente zu, so schlimm kann es also nicht sein. |
AW: Dateidownload
Zitat:
Zitat:
|
AW: Dateidownload
Zitat:
Frage: wäre es denn besser ein Record in einer Unit ohne Form abzulegen, eine Instanz zu erzeugen und auf diese Daten zuzugreifen? Dann wäre Form1 weg. Dann wäre es wenigstens ein wenig OOP und Synchronize bräuchte man auch nicht mehr. |
AW: Dateidownload
Zitat:
Wenn du es erklärst haben möchtest, mache bitte einen anderen Thread auf. |
AW: Dateidownload
Zitat:
|
AW: Dateidownload
Tutorial Threads:
![]() Zitat: Zitat:
Zitat:
Delphi-Quellcode:
type
TBinFertig = procedure(const Content: String) of object; TMyOwnThread = class(TThread) private FBinFertig: TBinFertig; procedure SyncBinFertig; public property BinFertig: TBinFertig read FBinFertig write FBinFertig; end; implementation procedure TMyOwnThread.SyncBinFertig; begin if Assigned(FBinFertig) then FBinFertig(DasIstDerInhaltDerWebseite); end; procedure TMyOwnThread.Execute; begin try // Download der Seite ... // Synchronisieren Synchronize(SyncBinFertig); except on e: exception do begin // mache hier irgendetwas mit dem Fehler. end; end; end; |
AW: Dateidownload
Heißt das also, dass man auch simple Variablen eines Records (NICHT Form1.xyz) synchronisieren muss?
Zum Beispiel EinRecord.sHTML := {SeiteDownloaden}; ? |
AW: Dateidownload
Solange der Record NUR im Thread Kontext Verwendung findet ist es entspannt. Ansonsten SYNCRONIZE und Event...
|
AW: Dateidownload
Hmm..
(Wiederholt in mehreren Posting hier im Forum!!!) ;) Zitat:
Wenn auf Variablen sowohl innerhalb des Threads(Execute) wie auch von außerhalb des Threads (Form.OnButtonClick) zugegriffen werden, dann MUSS IMMER Threadsave (Sychronisiert/Critical Section/SendMessage) gearbeitet werden!!! |
AW: Dateidownload
Man muss nur immer sehen, ob Synchronize oder CriticalSection für einen angemessen ist denn beide tun unterschiedliche Dinge soweit ich weiß.
Laut diesem Thread kann man auch mehreren Threads dieselbe CiriticalSection verpassen ![]() Nach dem Motto... CriticalSection.Enter; erzeuge 2 threads und lass sie arbeiten, CriticalSection.Leave; Könnte man so also den Downloadthread starten und ohne Synchronize im Thread selber alles anfassen und ändern? Denn drumrum liegt ja die CriticalSection oder nicht? Anderenfalls wenn es nur eine Instanz gibt ist das hier vielleicht die Lösung ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:07 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz