Bambini hat uns in seinem Beispiel leider gezeigt, wie man eine CriticalSection auf keinen Fall verwenden sollte.
1. Diese muss schon erstellt sein, bevor mehrere Threads mit den Daten arbeiten, sonst ist auch der schreibende Zugriff auf FLock unzulässig. Am besten im Constructor von TTeItemInfo.
2. Auch der Zugriff auf "list" muss geschützt werden, diese Variable ist nur eine Referenz auf ein Listenobjekt, das alle Threads verwenden.
3. Auch der Aufruf von DownloadInfo() liegt im geschützten Bereich, da dies sehr viel Zeit benötigt ist die Sperre fast permanent aktiv.
4. FOnUpdate wird nicht geschützt.
Ich versuch mich mal daran, hab aber das neue Delphi noch nicht:
Delphi-Quellcode:
procedure TTeItemInfo.AddSmallDataFromListAsync(list: TList<TeItemDB.TTeItemDBData>; lang: TTeLanguage);
var
DownloadList: array of record
id: string; // anderer Typ?
Value: string;
end;
i1, i2, id: Integer;
begin
{Daten für den Task vorbereiten}
i2 := 0;
for i1 := 0 to list.Count -1 do
begin
id := list[i1].id;
if not smalldata.ContainsKey(id) then
begin
SetLength(DownloadList, i2 + 1);
DownloadList[i2].id := id;
Inc(i2);
end;
end;
{Task ausführen}
if i2 > 0 then
begin
TTask.Run(
procedure
var
i: Integer;
begin
for i := 0 to Length(DownloadList) - 1 do
DownloadList[i].Value := DownloadInfo(DownloadList[i].id, lang.LoadedLanguage);
{Ergebnis an den Hauptthread übergeben}
TThread.Synchronize(nil,
procedure
var
i: Integer;
begin
for i := 0 to Length(DownloadList) - 1 do
if not smalldata.ContainsKey(DownloadList[i].id) then
AddSmallInfo(DownloadList[i].Value, DownloadList[i].id, lang);
if Assigned(FOnUpdate) then FOnUpdate(self);
end;
end;
end;
end;
Das einzig zeitintensive Teil ist "DownloadInfo()", nicht weil die Datenmenge so groß ist, sondern wegen der Latenz zwischen Anfrage und Antwort.
Besteht die Möglichkeit dem Dienst im Internet mehrere Anfragen in einem Block zu übertragen und die Antworten als Block zurück zu erhalten?
Das würde die Netzlast senken und die Geschwindigkeit insgesamt erhöhen.