AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Thread Programmierung für Downloadmanager
Thema durchsuchen
Ansicht
Themen-Optionen

Thread Programmierung für Downloadmanager

Ein Thema von mumu · begonnen am 3. Sep 2004 · letzter Beitrag vom 12. Jan 2005
Antwort Antwort
mumu

Registriert seit: 28. Okt 2003
Ort: Bamberg
519 Beiträge
 
#1

Thread Programmierung für Downloadmanager

  Alt 3. Sep 2004, 20:47
hi leute! ich bin zur zeit dabei eine art downloadmanager zu programmieren. dabei verwende ich die TidHttp komponente. ich bekomme aber immer die meldunge ungültiger fensterhandle, obwohl ich alle zugriffe mit criticalsections absichere.

hier einmal der code für einen downloadthread. ich starte in meinem programm bis zu 20 threads, welche die function download aufrufen.

Delphi-Quellcode:
function Download(p: Pointer): Integer;
var parameter: PDownloadParameter;
    weiteredownloads: boolean;
    url: string;
    ordner: string;
    responsestream: TFileStream;
    filename: string;
    doppelter_filename: string;
    doppelt: integer;
    notexists: boolean;
begin
  try
      Parameter := P;
      InterlockedExchangeAdd(Anzahl_der_Threads, 1);

      try
        weiteredownloads := true;
        while (weiteredownloads = true) do
        begin

          try
            // in CriticalSection eintreten, filelist sperren
            EnterCriticalSection(g_cs_gesamt);
              if (filelist.files.Count > 0) and
              (filelist.ordner.Count > 0) and
              (form1.Listview3.Items.Count > 0) then
              begin
                url := filelist.files.strings[0];
                filelist.files.Delete(0);
                ordner := filelist.ordner.strings[0];
                filelist.ordner.Delete(0);
                form1.Listview3.Items.delete(0);
                application.ProcessMessages;
              end else
              begin
                weiteredownloads := false;
              end;
            LeaveCriticalSection(g_cs_gesamt);

            // CriticalSection verlassen
          except
            weiteredownloads := false;
          end;

          if (url = '') or (ordner = '') then
          begin
            weiteredownloads := false;
          end else
          begin
            filename := url;
            delete(filename,1,LastDelimiter('/', filename));
          end;

          EnterCriticalSection(g_cs_gesamt);
            notexists := not fileexists(unit1.currentdir+'\'+ordner+'\'+filename);
          LeaveCriticalSection(g_cs_gesamt);
          if (weiteredownloads = true) and (notexists) then
          begin
            EnterCriticalSection(g_cs_gesamt);
              Parameter.Plabel.Caption := 'Download '+inttostr(Parameter.nr)+': '+filename;
            LeaveCriticalSection(g_cs_gesamt);
            application.ProcessMessages;

            EnterCriticalSection(g_cs_gesamt);
              responseStream := nil;
            LeaveCriticalSection(g_cs_gesamt);
            try
            // in CriticalSection eintreten, filesystem sperren
              EnterCriticalSection(g_cs_gesamt);
                if not directoryexists(unit1.currentdir+'\'+ordner) then
                begin
                  MkDir(currentdir+'\'+ordner);
                end;
                if fileexists(unit1.currentdir+'\'+ordner+'\'+filename) then
                begin
                  doppelt := 0;
                  repeat
                    doppelter_filename := unit1.currentdir+'\'+ordner+'\'+inttostr(doppelt)+filename;
                    doppelt := doppelt + 1;
                  until(not fileexists(doppelter_filename));
                    responseStream := TFileStream.Create(pchar(doppelter_filename), fmCreate);
                end else
                begin
                  responseStream := TFileStream.Create(pchar(unit1.currentdir+'\'+ordner+'\'+filename), fmCreate);
                end;
              LeaveCriticalSection(g_cs_gesamt);
              // CriticalSection verlassen
            except
            end;
            try
              try
                if responseStream <> nil then
                begin
                  application.ProcessMessages;
                  Parameter.dl.Get(url, responseStream);
                  application.ProcessMessages;
                // in CriticalSection eintreten, report sperren
                  EnterCriticalSection(g_cs_gesamt);
                    Succeed(url);
                  LeaveCriticalSection(g_cs_gesamt);
                // CriticalSection verlassen
                end else
                begin
                  // in CriticalSection eintreten, report sperren
                    EnterCriticalSection(g_cs_gesamt);
                      Fail(url, unit1.currentdir+'\'+ordner+'\'+filename);
                    LeaveCriticalSection(g_cs_gesamt);
                  // CriticalSection verlassen
                end;
              except
                // in CriticalSection eintreten, report sperren
                  EnterCriticalSection(g_cs_gesamt);
                    Fail(url, unit1.currentdir+'\'+ordner+'\'+filename);
                  LeaveCriticalSection(g_cs_gesamt);
                // CriticalSection verlassen
              end;
            finally
              responseStream.free;
            end;
          end;
        end;
      finally
      end;
      EnterCriticalSection(g_cs_gesamt);
        Parameter.Plabel.Caption := 'FERTIG!';
        CloseThread();
      LeaveCriticalSection(g_cs_gesamt);
      result := 1;
  except
    Result := 2;
  end;
end;
  Mit Zitat antworten Zitat
Benutzerbild von SleepyMaster
SleepyMaster

Registriert seit: 18. Mai 2003
634 Beiträge
 
#2

Re: Thread Programmierung für Downloadmanager

  Alt 4. Sep 2004, 17:38
application.ProcessMessages; in einm Thread ist soweit ich weiß sehr großer Schwachsinn. Vielleicht kommt daher sogar der Fehler. Ansonsten kann ich dir bei dem kleinen Fetzen Code nicht helfen.

Vielleicht gibst du mal den ganzen Code raus (oder sendest den mir per PM)
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.195 Beiträge
 
Delphi 10.4 Sydney
 
#3

Re: Thread Programmierung für Downloadmanager

  Alt 4. Sep 2004, 17:45
Die Delphi VCL-Klassenbibliothek ist nicht Thread-Save. Alle Aktionen welche sich auf Oberflächenelemente beziehen müssen im Kontext des Hauptthreads stattfinden.

Schau in der Delphi-Hilfe mal nach TThread.Synchronize wie du von deinem Thread zugriff auf den Hauptthread hast, um deinen Thread und den "Rest" des Programms zu synchronisieren.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
mumu

Registriert seit: 28. Okt 2003
Ort: Bamberg
519 Beiträge
 
#4

Re: Thread Programmierung für Downloadmanager

  Alt 5. Sep 2004, 18:10
also das application.processmessages ist da normalerweise nicht drin. war blos weil ich was im hauptthread testen wollte. der fehler kommt also nicht daher...

ja es ist mir klar dass die VCL nicht threadsafe ist, daher verwende ich ja critical sections. synchronize ist ja nur beim VCL threadobjekt verfügbar. ich muss aber auf jeden fall mit BeginThread meine threads starten.
  Mit Zitat antworten Zitat
mumu

Registriert seit: 28. Okt 2003
Ort: Bamberg
519 Beiträge
 
#5

Re: Thread Programmierung für Downloadmanager

  Alt 8. Sep 2004, 11:01
also ich hab den code jetzt zu einem TThread-Object umgeändert und statt critical sections hab ich synchronize verwendet. und jetzt funktioniert alles!!! obwohl ich sonst gar nix am quellcode geändert hab. das gibts doch nicht??? ist das im grunde nicht das selbe synchronize und critical sections??? weiß jemand woran das liegt?

danke schonmal
  Mit Zitat antworten Zitat
mumu

Registriert seit: 28. Okt 2003
Ort: Bamberg
519 Beiträge
 
#6

Re: Thread Programmierung für Downloadmanager

  Alt 12. Jan 2005, 13:25
einen alten thread mal wieder nach oben holen!!! weiß immer noch nicht woran das liegt?
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.483 Beiträge
 
Delphi 10.1 Berlin Professional
 
#7

Re: Thread Programmierung für Downloadmanager

  Alt 12. Jan 2005, 13:35
Die CriticalSection synchronisiert nicht mit dem Hauptthread sondern mit sich selbt. Eine VCL-Anweisung in einem Thread wird immer im Kontext des Threads ausgeführt und nicht im Hauptthread. Dazu gibt es TThread.Synchronize, das die übergebe Methode in eine Liste steckt und dann den Thread solange blockiert, bis der Hauptthread in der Botschaftsschleife die Synchronize-Liste abgearbeitet (aufgerufen) hat. Danach geht es im Thread weiter. Der VCL Code in der zu synchronisierenden Methode wird also nicht vom Thread aufgerufen, sondern vom Hauptprogramm und das in der Messageloop.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#8

Re: Thread Programmierung für Downloadmanager

  Alt 12. Jan 2005, 13:41
Ich hatte noch nie Probleme Kontrolls auf dem Formular aus einem Thread raus anzusprechen. Allerdings übergebe ich sie immer als Parameter an den Thread.

@mumu: Wie ist dein TDownloadParameter Record aufgebaut? Wenn du Strings verwendest, dann dürfen das nur ShortStrings sein.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
w3seek
(Gast)

n/a Beiträge
 
#9

Re: Thread Programmierung für Downloadmanager

  Alt 12. Jan 2005, 14:56
Zitat von Luckie:
Ich hatte noch nie Probleme Kontrolls auf dem Formular aus einem Thread raus anzusprechen. Allerdings übergebe ich sie immer als Parameter an den Thread.
Da hattest du nur verdammt viel Glück, wie bereits erwähnt ist die VCL selbst nicht thread-safe...
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:22 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