Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi OnWork wird nach Download ausgeführt? (https://www.delphipraxis.net/111050-onwork-wird-nach-download-ausgefuehrt.html)

TheMiller 28. Mär 2008 15:30


OnWork wird nach Download ausgeführt?
 
Hallo,

ich habe die Indy-Komponente in einen Thread gesteckt und ein onWork-Event programmiert. Doch leider wird das onWork erst nach dem vollendeten Download ausgeführt.

Hier mal mein Code..

Delphi-Quellcode:
[..]

  private
    procedure WorkProgress(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);

[..]
// TThread.Execute
 
  if (Download) then
    begin
      www:=TIdHttp.Create(nil);
      [url]www.OnWork:=WorkProgress;[/url]
      fs:=TFileStream.Create(DownloadDest+DownloadFile, fmCreate);
      try
        www.Get(DownloadPath+'/'+DownloadFile, fs);
      finally
        [url]www.Free;[/url]
      end;
      if Assigned(FParent.fOnFileComplete) then Synchronize(FParent.DoFileComplete);
    end;


procedure TThread.WorkProgress(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
begin
  //Diese Box erscheint mehrmals (und ist nur ein Test)
  MessageBox(0, 'sad', 'sadsad', 0);
end;
Danke im Voraus!

MrKnogge 28. Mär 2008 16:34

Re: OnWork wird nach Download ausgeführt?
 
Nutzt du einen Proxy-Server ?
Ich hab zwar bisher noch nicht mit TIdHttp im zusammenhang mit Threads gearbeitet, hatte das Phänomen aber schon, wenn ich die Proxyfunktion von TIdHttp verwendet habe. (weis jetzt aber nicht, ob der Fehler bei den Indys oder am Proxy liegt)

TheMiller 28. Mär 2008 16:44

Re: OnWork wird nach Download ausgeführt?
 
Nein, ich nutze keinen Proxy-Server. Das kommt mir aber sehr seltsam vor. Warum sollte es NACH den Download ausgeführt werden? Die Ausführung an sich ist korrekt. Die Methode wird auch öfter mit steigenden AWorkCount-Werten aufgefufen. Nur halt eben nach dem Download!

MrKnogge 28. Mär 2008 16:54

Re: OnWork wird nach Download ausgeführt?
 
Wenn sie mehrmals aufgerufen wird ist doch alles korrekt!
Wann sollte sie denn deiner Meinung nach aufgerufen werden ?

TheMiller 28. Mär 2008 16:57

Re: OnWork wird nach Download ausgeführt?
 
WÄHREND dem Download sollte die Methode aufgerufen werden. Sie gibt nämlich die bereits geladenen Bytes wieder.

Bei mir wird sie NACH dem Download aufgerufen, also wenn die Datei schon auf dem Rechner ist...

MrKnogge 28. Mär 2008 17:00

Re: OnWork wird nach Download ausgeführt?
 
OK, ich hatte es so verstanden, dass die Datei noch nicht komplett auf dem Rechner ist.

TheMiller 28. Mär 2008 17:02

Re: OnWork wird nach Download ausgeführt?
 
Hm... und nu?

Christian Seehase 28. Mär 2008 17:40

Re: OnWork wird nach Download ausgeführt?
 
Moin DJ-SPM,

hast Du es bisher nur mit der MessageBox versucht?
Wenn ja, probier mal einfach den WorkCount in ein Label oder ähnliches zu schreiben, und lass die MessageBox weg.

TheMiller 28. Mär 2008 18:08

Re: OnWork wird nach Download ausgeführt?
 
Hallo!

Zeigt leider keine Veränderung!

Dani 28. Mär 2008 19:38

Re: OnWork wird nach Download ausgeführt?
 
Wie groß ist die Datei?

SirThornberry 28. Mär 2008 19:45

Re: OnWork wird nach Download ausgeführt?
 
Zitat:

Zitat von DJ-SPM
WÄHREND dem Download sollte die Methode aufgerufen werden. Sie gibt nämlich die bereits geladenen Bytes wieder.

Bei mir wird sie NACH dem Download aufgerufen, also wenn die Datei schon auf dem Rechner ist...

Die Bytes? Die Indy-Version die ich habe/hatte hat nie die Bytes im OnWork angegeben sondern eine Einheit die unbestimmt ist. Wenn man die genauen Bytes wissen will sollte man sich seine eigene Streamklasse basteln und dort das WriteBuffer (bzw. die entsprechende Methode wenn es nicht diese ist) übeschreiben.

TheMiller 28. Mär 2008 20:02

Re: OnWork wird nach Download ausgeführt?
 
Ok SirThornberry,

das mag sein, ist in meinem Fall aber auch egal. Die Datei ist 2MB groß

SirThornberry 28. Mär 2008 20:03

Re: OnWork wird nach Download ausgeführt?
 
egal ist es in deinem fall nicht ganz. Denn das OnWork wird nicht so oft aufgerufen wie die Write-Methode des Streams. Willst du also wirklich viel Feedback solltest du unbedingt an dieser Stelle ansetzen.

TheMiller 28. Mär 2008 20:08

Re: OnWork wird nach Download ausgeführt?
 
Ich möchte einfach nur "schnell" indizieren, dass eine Datei gerade geladen wird und dieser Download fortschritt macht.

Dani 28. Mär 2008 20:10

Re: OnWork wird nach Download ausgeführt?
 
Woran merkst du eigentlich, dass OnWork erst aufgerufen wird, wenn die Datei schon fertig runtergeladen ist? Ist das auch der Fall, wenn du ShowMessage weglässt und nicht mit dem Debugger in der OnWork Methode anhältst?

TheMiller 28. Mär 2008 20:14

Re: OnWork wird nach Download ausgeführt?
 
Ich lasse eine Nachricht anzeigen, wenn die Datei geladen ist. Und nach der Nachricht wird das ausgeführt, was im OnWork steht. Ob das MessageBoxen sind, Änderungen in Label etc...

SirThornberry 28. Mär 2008 20:15

Re: OnWork wird nach Download ausgeführt?
 
Zitat:

Zitat von DJ-SPM
Ich möchte einfach nur "schnell" indizieren, dass eine Datei gerade geladen wird und dieser Download fortschritt macht.

Dann schau dir auf jeden fall die Methode mit dem Stream an:
http://www.delphipraxis.net/internal...=563250#563250

(den gesamten Thread dort anschauen, der gepostete Quelltext in diesem Beitrag enthielt noch einen Fehler - es wurde von TMemoryStream anstelle von TFileStream abgeleitet)

TheMiller 28. Mär 2008 20:17

Re: OnWork wird nach Download ausgeführt?
 
Danke. Werde ich machen. Nur leider geht das jetzt nicht.

SirThornberry 28. Mär 2008 20:18

Re: OnWork wird nach Download ausgeführt?
 
woran scheitert es momentan diese variante umzusetzen?

TheMiller 28. Mär 2008 20:19

Re: OnWork wird nach Download ausgeführt?
 
Achso.. moment.

Ich meine damit, dass ich jetzt nicht programmieren kann. Ich werde es mir also später anschauen. sorry

TheMiller 29. Mär 2008 12:42

Re: OnWork wird nach Download ausgeführt?
 
Hallo, es funktioniert leider immernoch nicht. Kann das vielleicht daran liegen, dass der Thread innerhalb einer Containerklasse aufgerufen wird? Hier mal der relevante Quelltext:

Erstmal die Hauptform

Delphi-Quellcode:
  private
    procedure ShowWork(Sender: TObject; AWorkCount: Integer);
  end;

procedure TForm1.ShowWork(Sender: TObject; AWorkCount: Integer);
begin
  Form1.Caption:=IntToStr(AWorkCount);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  //Updater ist global!
  Updater:=TContainer.Create;
  Updater.SeekUpdates;
  Updater.onAfterCheck:=Updates;
  Updater.onFileComplete:=Complete;
  Updater.OnWork:=ShowWork;
end;
Hier die Containerklasse mit dem Thread

Delphi-Quellcode:

// Der Container
type
  TAfterUpdateCheck = procedure(Sender: TObject) of Object;
  TFileComplete = procedure(Sender: TObject) of Object;
  TOnWorkEvent = procedure(Sender: TObject; AWorkCount: Integer) of object;

  TContainer=class(TSimpleRWSync)
    //[...]
  private
    FOnWorkEvent: TOnWorkEvent;
    procedure InternalOnWork(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
    procedure DoNotifyWork;
  public
    property OnWork: TOnWorkEvent read FOnWorkEvent write FOnWorkEvent;

// Der Thread
type
  TDownloadThread = class(TThread)
  public
    FParent: TContainer;
    SeekUpdates: Boolean;
    Download: Boolean;
    DownloadDest: String;
    DownloadPath: String;
    DownloadFile: String;
  private
    procedure WorkProgress(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
  protected
    procedure Execute; override;
  end;

procedure TDownloadThread.Execute;
var
  www: TIdHTTP;
  fs: TFileStream;
  ini: TMemInifile;
  i, size, imp: Integer;
  Title, Filename, Version, Desc, Path: String;
  PlugIn: Boolean;
  tmpUpdates, Updates: TStrings;
begin
  www:=TIdHTTP.Create(nil);
  try
   //[...]
    if (Download) then
    begin
      www:=TIdHttp.Create(nil);
      [url]www.OnWork:=FParent.InternalOnWork;[/url]
      fs:=TFileStream.Create(DownloadDest+DownloadFile, fmCreate);
      try
        www.Get(DownloadPath+'/'+DownloadFile, fs);
      finally
        [url]www.Free;[/url]
      end;
      if Assigned(FParent.fOnFileComplete) then Synchronize(FParent.DoFileComplete);
    end;
  finally
    fs.Free;
    ini.Free;
    Updates.Free;
  end;
end;

//===== Container =======

procedure TContainer.InternalOnWork(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
begin
  FWorkCount := AWorkCount;
  TDownloadThread.Synchronize(nil, DoNotifyWork);
end;

procedure TContainer.DoNotifyWork;
begin
  Assert(Assigned(FOnFileComplete));
  OnWork(Self, FWorkCount);
end;

procedure TContainer.SeekUpdates;
var
  Dt: TDownloadThread;
begin
  Dt:=TDownloadThread.Create(True);
  Dt.FreeOnTerminate:=True;
  Dt.FParent:=Self;
  Dt.SeekUpdates:=True;
  Dt.Download:=False;
  Dt.Resume;
end;
Es sollte so sein, dass das MainForm dem Container sagen soll, dass er den Download starten muss, der Container sammelt in einem Array die Downloads und startet intern den Download-Thread. Die Dateien werden runtergeladen und das OnWork von TIdHTTP sollte durch den Container in die MainForm gereicht werden. Das klappt, aber erst, wenn die Datei schon geladen wurde. Danach wird das OnWork mehrmals (ca 5-7 mal) ausgefüht.

Wenn ich TFileStreamEx verwende, passiert leider garnichts. Ich habe auch die Klasse korrigiert (MemoryStream -> FileStream) Vielleicht liegst an meiner Container-Thread-Konstruktion

Danke

TheMiller 29. Mär 2008 13:33

Re: OnWork wird nach Download ausgeführt?
 
Halt! Neuer Erkenntnis:

Selbst wenn ich ein neues Projekt ohne Container, Thread etc erstelle, tritt der gleiche Fehler auf. Hier nochmal der Code des neuen Projekts

Delphi-Quellcode:
  private
    procedure InternalOnWork(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
  public

procedure TForm1.InternalOnWork(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
begin
  ShowMessage('SD');
  Form1.Caption:=IntToStr(AWorkCount);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  www: TIdHTTP;
  fs: TFileStream;
begin
  fs:=TFileStream.Create(ExtractFilePath(ParamStr(0))+'text.zip', fmCreate);
  www:=TIdHttp.Create(nil);
  [url]www.OnWork:=InternalOnWork;[/url]
  www.Get('http://www.domain.de/updates/Putty.exe', fs);
  ShowMessage('Fertig');
end;
Es erscheint die Message "Fertig" und danach mehrmals "SD" und die Caption verändert sich... Halt alles nach Download! Wieso? :wall: :wall:

Christian Seehase 29. Mär 2008 15:03

Re: OnWork wird nach Download ausgeführt?
 
Moin DJ-SPM,

lass' mal ShowMessage weg.
Das bringt die Verarbeitung der MessageQueue durcheinander.
Benutze, ersatzweise, mal OutputDebugString, dann kannst Du Dir im EventLog-Fenster (Ansicht\Debug Fenster) den Ablauf anschauen.

TheMiller 29. Mär 2008 15:08

Re: OnWork wird nach Download ausgeführt?
 
Ich habe mittlerweile gesehen, dass alles richtig funktioniert, wenn ich eine Datei runterlade, die größer als 2MB ist. Bei kleineren Dateien tritt der Fehler wieder auf. Auch in einem komplett neuen Projekt.

Habe das ShowMessage auch schon weggelassen.

Habe eine MP3-Datei auf einen Server geladen und diese mit dem Programm runtergeladen und es at wunderbar UND synchron funktioniert. Dann wieder eine 1,2MB-Datei und da ging's dann wieder erst NACH dem Download los.

Und von "OutputDebugString" habe ich keine Ahnung. Das sagt mir garnix!

Christian Seehase 29. Mär 2008 15:14

Re: OnWork wird nach Download ausgeführt?
 
Moin DJ-SPM,

OutputDebugString schreibt den angegebenen Text in das Eventlog.
Damit kann man dann wunderbar (vorausgesetzt man schreibt sinnvolle Text weg ;-)) den Ablauf verfolgen.

Das OnWork-Event wird immer ausgelöst, wenn der Buffer gefüllt wurde. Der Default-Wert müsste 32 KB betragen.
In meinem Download-Thread mache ich es mit TidHTTP auch nicht anders, als Du es oben beschrieben hast, und, so wie es aussieht, funktioniert es.

TheMiller 29. Mär 2008 15:18

Re: OnWork wird nach Download ausgeführt?
 
Ja, aber wenn ich doch eine Datei lade, die 1,2MB groß ist, dann werden doch mehrere Male 32kb geschrieben. Also müsste doch auch mehrere male das onWork ausgeführt werden, nämlich immer dann, wenn 32kb voll sind.

Eigentlich wird es ja auch mehrere Male ausgeführt. Nur eben bei Dateien kleiner als xMB nach dem vollständigen Download, bei größeren Dateien (getestet mit MP3-Datei von 4MB) korrekt während dem Download.

Egal was ich mache, alles was in OnWork steht wird je nach Dateigröße mal früher mal später ausgeführt.

das verstehe ich nicht

Christian Seehase 29. Mär 2008 15:35

Re: OnWork wird nach Download ausgeführt?
 
Moin DJ-SPM,

leider kann ich das Problem nicht nachstellen, da ich eine andere Version der Indys verwende (ich weiss nicht einmal welche genau :oops:).
Bei mir ist AWorkCount nicht als const deklariert.

TheMiller 29. Mär 2008 15:38

Re: OnWork wird nach Download ausgeführt?
 
Liste der Anhänge anzeigen (Anzahl: 2)
Ich hab mal einen Anhang hochgeladen. Dabei verwende ich auch OutputDebugString... Da habe ich einen RICHTIG-Knop und einen Falsch Knopf. Schau mal bitte.

MrKnogge 29. Mär 2008 16:43

Re: OnWork wird nach Download ausgeführt?
 
Also bei mir funktionieren beide Knöpfe wunderbar, die Progressbar zeigt prima den aktuellen Stand an. Hast du es nur in der IDE getestet, oder auch auserhalb der IDE ?
Was ein Label im OnWork angeht, so bewirkt nach dem Setzen der Caption ein Label.refresh Wunder.

Grüße
Christian

PS: Hast du mal versucht deine Indys zu aktualisieren ?

TheMiller 29. Mär 2008 17:46

Re: OnWork wird nach Download ausgeführt?
 
Also bei mir ist das so (ich habe Windows Vista Business), dass bei Knopf 1 erst eine Weile garnix passiert und dann die Progressbar razz-fazz (oder so) gefüllt wird.

ABER: Ganz generell habe ich solche Sachen schon mit Vista beim Download festgestellt. Zb, wenn ich eine größere Datei per IE runterlade (also komplett ohne Delphi), dann läd der mit 90kb (ich kann mit DSL2000 bei zu 220 laden), sagt, dass es noch 5 Minuten dauert, an auf einmal sagt er, dass er fertig ist.

Da stimmt also generell was mit der Download-Anzeige nicht. 100MB dauern ca 7 Minuten. Manchmal zeigt er also an, dass der Download 20-30 Minuten dauert, läd aber doch (intern) mit der richtigen Geschwindigkeit und sagt dann (nach der richtig Zeit), dass er fertig ist.

Ich weis nicht, wie ich es anders beschreiben soll.

Und die progressbar wird wirklich bei dir nach und nach gefüllt, und nicht erst am Schluss ganz schnell?

[EDIT]Hab's gerade an einem nicht-Vista-Rechner getestet und es funktioniert tatsächlich. Damit bestätigt sich die oben geschriebene Vermutung. Das mit der falschen Download-Anzeige ist wirklich ganz extrem. Ist das ein bekannter Vista-Bug, oder habe mal wieder nur ich so ein Problem?[/EDIT]

MrKnogge 29. Mär 2008 17:58

Re: OnWork wird nach Download ausgeführt?
 
Ja, ich habe nur DSL-Light (384Kb/s) und es geht schleppend vorran.
Ich habe leider kein Vista zum testen, werde mich aber mal in meinem Bekanntenkreis dazu umhören. Hast du Vista RC1 bereits installiert?

TheMiller 29. Mär 2008 18:01

Re: OnWork wird nach Download ausgeführt?
 
Wenn du das SP für Vista meinst, dann ja!

Das wäre echt nett!


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:32 Uhr.

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