![]() |
Thread Programmierung für Downloadmanager
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; |
Re: Thread Programmierung für Downloadmanager
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) |
Re: Thread Programmierung für Downloadmanager
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. |
Re: Thread Programmierung für Downloadmanager
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. |
Re: Thread Programmierung für Downloadmanager
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 |
Re: Thread Programmierung für Downloadmanager
einen alten thread mal wieder nach oben holen!!! ;-) weiß immer noch nicht woran das liegt?
|
Re: Thread Programmierung für Downloadmanager
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.
|
Re: Thread Programmierung für Downloadmanager
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. |
Re: Thread Programmierung für Downloadmanager
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:55 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