Einzelnen Beitrag anzeigen

Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.477 Beiträge
 
Delphi 12 Athens
 
#4

AW: Problem: Mehrere Threads auf ein Dictionary

  Alt 11. Mai 2015, 16:14
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.
  Mit Zitat antworten Zitat