![]() |
AW: TList mit Record füllen und an weitere TList übergeben
Dein Problem ist offenbar nicht mehr die TList sondern die Synchronisierung von Threads.
In dem Fall wäre das dann auch ein Thema für einen neuen "Thread". ;-) Hier gab es kürzlich eine nette Zusammenfassung: ![]() |
AW: TList mit Record füllen und an weitere TList übergeben
Ich habe alles Unwichtige rausgenommen und ein bisschen Pseudo-Kommentiert, damit man es HALBWEGS nachvollziehen kann :lol:
Threads sind nicht das Problem. Denn als ich das alles ohne ObjectList hatte, lief es einwandfrei.
Delphi-Quellcode:
// aProcessFileList_ObjectList enthält "10" Instanzen von TFileEntry
// aProcessFileList_ObjectList.OwnsObjects ist "False" // aGlobalVars.iMaxCopyThreadCount ist "2" // iFilesPerThread ist "5" // Der ganze StringList-Kram ist nur zum TEST da {* Dateien z.B.: - Datei0.txt - Datei1.txt - Datei2.txt - Datei3.txt - Datei4.txt - Datei5.txt - Datei6.txt - Datei7.txt - Datei8.txt - Datei9.txt *} aTmpFileList_ObjectList := TObjectList.Create; aTmpFileList_ObjectList.OwnsObjects := False; try for i := 0 to aGlobalVars.iMaxCopyThreadCount - 1 do begin Application.ProcessMessages; try if aProcessFileList_ObjectList.Count >= iFilesPerThread then begin // Liste wird geleert, damit nicht die alten Daten drin sind / SEIN SOLLTEN aTmpFileList_ObjectList.Clear; iCnt := iFilesPerThread; if aProcessFileList_ObjectList.Count - iCnt = 1 then Inc(iCnt); {* Erster Durchgang: aTmpFileList_ObjectList bekommt "Datei0" bis "Datei4" Zweiter Durchgang: aTmpFileList_ObjectList bekommt "Datei5" bis "Datei9" *} for j := 0 to iCnt - 1 do aTmpFileList_ObjectList.Insert(j, aProcessFileList_ObjectList.Items[j]); sl := TStringList.Create; try {* Erster Durchgang: aus aProcessFileList_ObjectList wird "Datei4" bis "Datei0" gelöscht Zweiter Durchgang: aus aProcessFileList_ObjectList wird "Datei9" bis "Datei5" gelöscht *} for j := iCnt - 1 downto 0 do begin aProcessFileList_ObjectList.Delete(j); sl.Add(TFileEntry(aTmpFileList_ObjectList.Items[j]).sSourceDirItem); end; // StringList-TEST - was ist in der Liste? In eine Datei abspeichern! sl.SaveToFile(ExtractFilePath(ParamStr(0)) + '__DELETE' + IntToStr(i) + '.txt'); finally sl.Free; end; sl := TStringList.Create; try for j := 0 to aTmpFileList_ObjectList.Count - 1 do begin sl.Add(TFileEntry(aTmpFileList_ObjectList.Items[j]).sSourceDirItem); end; // StringList-TEST - was ist in der Liste? In eine Datei abspeichern! sl.SaveToFile(ExtractFilePath(ParamStr(0)) + '__' + IntToStr(i) + '.txt'); finally sl.Free; end; if aTmpFileList_ObjectList.Count > 0 then begin {* Erster Durchgang: Thread1 arbeitet "Datei0" bis "Datei4" ab Zweiter Durchgang: Thread2 arbeitet "Datei5" bis "Datei9" ab *} createCopyThread(aTmpFileList_ObjectList); end; end else break; except // ... end; end; // Wenn noch RESTE in der originalen ObjectList sind, dann erstelle damit einen seperaten Thread // Das ist z.B. der Fall, wenn 11 Dateien verarbeitet werden müssten. Die letzte (elfte) Datei würde hier in einen Thread gepackt werden if aProcessFileList_ObjectList.Count > 0 then begin createCopyThread(aProcessFileList_ObjectList); end; end; finally aTmpFileList_ObjectList.Free; end; //////////////////////////////////////////////////////////////////////////////// procedure createCopyThread(FaFileList: TObjectList); var aCopyThread: TCopyThread; begin aCopyThread := TCopyThread.Create; aCopyThread.aFileList := FaFileList; end; //////////////////////////////////////////////////////////////////////////////// type TCopyThread = class(TThread) private { Private-Deklarationen } FaFileList: TObjectList; protected procedure Execute; override; public { Public-Deklarationen } constructor Create; procedure Finish(Sender: TObject); property aFileList: TObjectList read FaFileList write FaFileList; end; |
AW: TList mit Record füllen und an weitere TList übergeben
Zitat:
|
AW: TList mit Record füllen und an weitere TList übergeben
Zitat:
Aber ich übergebe dem Thread doch die ObjectList. Hat der dann nicht eine vollkommen eigene Kopie davon? Und wenn ich dann das Original (aTmpFileList_ObjectList) ändere, dürfte das die Daten im Thread doch nicht ändern. |
AW: TList mit Record füllen und an weitere TList übergeben
Zitat:
Du könntest den Aufruf beim Thread als const definieren, dann wird eine Kopie deiner Liste erstellt:
Delphi-Quellcode:
procedure createCopyThread(const FaFileList: TObjectList);
... |
AW: TList mit Record füllen und an weitere TList übergeben
Wieso sollte da eine Kopie erstellt werden?
|
AW: TList mit Record füllen und an weitere TList übergeben
Zitat:
Des Weiteren könntest du auch folgenden machen:
Delphi-Quellcode:
.
aTmpFileList_ObjectList := TObjectList<TFileEntry>.Create(False);
Das hat 2 Vorteile:
|
AW: TList mit Record füllen und an weitere TList übergeben
Das mit dem Zeiger wusste ich nicht. Ich dachte die ObjectList wird ganz normal übergeben und die Procedur hat dann davon eine Kopie.
Klingt jetzt verdächtig nach einem Array von ObjectListen wenn ich das richtig verstanden habe? Ihr seid so genial :-D Es funktioniert nun. Ich packe nun alle Instanzen in ObjectLists, die bei Gebraucht erzeugt werden. Verwaltet werden sie in einem dynamischen Array of TObjectList. |
AW: TList mit Record füllen und an weitere TList übergeben
Zitat:
Hier mal ein Beispiel wie ich es machen würde (ungetestet und nur hier runtergetippt):
Delphi-Quellcode:
try for i := 0 to aGlobalVars.iMaxCopyThreadCount - 1 do begin Application.ProcessMessages; // <--- Das hier brauchst du normalerweise nicht, da die Aktion so schnell abläuft, dass du davon sehr wahrscheinlich nichts mitbekommst try if aProcessFileList_ObjectList.Count >= iFilesPerThread then begin aTmpFileList_ObjectList := TObjectList<TFileEntry>.Create(False); // <-------------- ObjectList erst hier erzeugen. Somit kommen die sich nicht in die Quere. // aTmpFileList_ObjectList.OwnsObjects := False; // Durch den False Parameter entfällt diese Zeile // Liste wird geleert, damit nicht die alten Daten drin sind / SEIN SOLLTEN // aTmpFileList_ObjectList.Clear; // Das hier brauchst du normal auch nicht, da eine Liste beim Erstellen immer leer ist/sein sollte iCnt := iFilesPerThread; if aProcessFileList_ObjectList.Count - iCnt = 1 then Inc(iCnt); {* Erster Durchgang: aTmpFileList_ObjectList bekommt "Datei0" bis "Datei4" Zweiter Durchgang: aTmpFileList_ObjectList bekommt "Datei5" bis "Datei9" *} for j := 0 to iCnt - 1 do aTmpFileList_ObjectList.Add(aProcessFileList_ObjectList.Items[j]); CreateWorkingThread(aTmpFileList); end; finally // Blubb end; end; finally end;
Delphi-Quellcode:
Nicht hauen, wenn ich jetzt etwas vergessen oder mich irgendwo vertippt habe. :-D
procedure TWorkingThread.Execute;
begin // Do something here FTmpFileList.Free; // Hier die beim Erzeugen des Threads übergebene ObjectList freigeben end; |
AW: TList mit Record füllen und an weitere TList übergeben
Die Prozedur erhält eine Referenz auf die Objektliste.
Sie benutzt also die gleiche Liste. Eine Kopie der Liste könntest Du erzeugen, wenn Du eine neue Listeninstanz erzeugst und die Einträge kopierst. Wenn die Einträge Objekte sind, kopierst Du aber auch nur wieder Referenzen auf die Listeneinträge. Du kannst das analog
Delphi-Quellcode:
sehen.
Panel2 := Panel1
Hier wird der Variablen Panel2 ja auch nur eine andere Referenz (ein anderer Pointer) zugewiesen. PS: Sehe gerade, dass Du es gelöst hast. Aber Dein "Array of ObjectList" kann ich nicht ganz nachvollziehen. Egal, wenn es läuft, läuft es :-) Vielleicht kannst Du es ja später nochmal anders ordnen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:34 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