AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TTask & Synchronize Verständnisproblem

Ein Thema von weisswe · begonnen am 19. Apr 2017 · letzter Beitrag vom 20. Apr 2017
Antwort Antwort
Seite 1 von 2  1 2      
weisswe
(Gast)

n/a Beiträge
 
#1

TTask & Synchronize Verständnisproblem

  Alt 19. Apr 2017, 11:36
Delphi-Version: 10 Berlin
Hallo!

Habe ein Verständnisproblem bei TTask.
Wollte nur Variablen der "Hauptprocedur" an den Task beim Start übergeben.
Jedoch bekomme ich nicht die richtigen Werte (meist -> 1,2,3,4,6,6).
Ich verstehe ja, das die Tasks unabhängig/zeitversetzt gestartet werden - nur wie bekomme ich Variablen "synchronisiert" beim Start des Tasks in den Task.
Hoffe habe mich irgendwie verständlich ausgedrückt.

Delphi-Quellcode:
   SetLength(tasks, anz);
   for i := 0 to anz - 1 do
   begin
      fn := Files[i].Filename;
      s := fn + ' wird heruntergeladen...';
      line := Memo1.Lines.Add(s);
      Files[i].Zeilennummer := line;
      tasks[i] := TTask.Create (
         procedure ()
         var j: Integer;
             tfn, ss: String;
         begin
            TInterlocked.Exchange(j, i); // !!?? zu spät?
            TThread.Synchronize(nil,
            procedure
            begin
               tfn := fn; // !!?? zu spät?
            end);
            ok := DownloadFile(tfn); // Herunterladen - zeitintensiv
            TThread.Synchronize(nil,
            procedure
            begin
               ss := tfn + ' wurde heruntergeladen.';
               Memo1.Lines.Add(IntToStr(j) + ' - ' + ss);
            end);
         end);
      tasks[i].Start;
   end;
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#2

AW: TTask & Synchronize Verständnisproblem

  Alt 19. Apr 2017, 11:54
Innerhalb der anonymen Methode wird immer der gerade aktuelle Wert der Variablen i und fn verwendet. Da dieser zur Ausführung in der Task schon ein anderer sein kann als zur Erzeugung der Task, kommt es zu diesem Verhalten. Du kannst aber die anonyme Methode auch über eine Funktion erzeugen lassen, der du den i- und fn-Parameter mitgibst. Dabei erhalten die Parameter ihre Werte aus dem Hauptthread und stehen der Task exklusiv zur Verfügung (Code ungetestet).

Delphi-Quellcode:
function CreateMyTask(I: Integer; fn: string; HandleResult: TProc<string>): TProc;
begin
  result :=
    procedure ()
    var
      ok: Boolean;
    begin
      ok := DownloadFile(fn); // Herunterladen - zeitintensiv
      TThread.Synchronize(nil,
        procedure
        var
          ss: String;
        begin
          if ok then begin
            ss := fn + ' wurde heruntergeladen.';
          end
          else begin
            ss := fn + ' wurde nicht heruntergeladen.';
          end;
          HandleResult(IntToStr(i) + ' - ' + ss);
        end);
    end;
end;

...

   SetLength(tasks, anz);
   for i := 0 to anz - 1 do
   begin
      fn := Files[i].Filename;
      s := fn + ' wird heruntergeladen...';
      line := Memo1.Lines.Add(s);
      Files[i].Zeilennummer := line;
      tasks[i] := TTask.Create(CreateMyTask(i, fn,
        procedure (Arg: string)
        begin
          Memo1.Lines.Add(Arg);
        end));
      tasks[i].Start;
   end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.176 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: TTask & Synchronize Verständnisproblem

  Alt 19. Apr 2017, 11:57
Und spätestens hier sollte man anhand der Lesbarkeit sehen dass es besser wäre das Herunterladen und das Anzeigen in der Oberfläche zu trennen. Auf Dauer bleibt es bestimmt nicht bei einem einfachen Memo1.Lines.Add(..) ...
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#4

AW: TTask & Synchronize Verständnisproblem

  Alt 19. Apr 2017, 13:04
Und spätestens hier sollte man anhand der Lesbarkeit sehen dass es besser wäre das Herunterladen und das Anzeigen in der Oberfläche zu trennen. Auf Dauer bleibt es bestimmt nicht bei einem einfachen Memo1.Lines.Add(..) ...
Vielleicht dann besser gleich so?

Dazu kommt noch, daß das Synchronize eh die letzte Aktion der Task ist und somit auch durch ein Queue ersetzt werden kann.

Delphi-Quellcode:
function CreateMyTask(I: Integer; fn: string; HandleResult: TProc<Integer, string, Boolean>): TProc;
begin
  result :=
    procedure ()
    var
      ok: Boolean;
    begin
      ok := DownloadFile(fn); // Herunterladen - zeitintensiv
      TThread.Queue(nil,
        procedure
        begin
          HandleResult(i, fn, ok);
        end);
    end;
end;

function CreateResultHandler(Target: TStrings): TProc<Integer, string, Boolean>;
begin
  Result :=
    procedure (Idx: Integer; FileName: string; OK: Boolean)
    var
      ss: string;
    begin
      if OK then begin
        ss := FileName + ' wurde heruntergeladen.';
      end
      else begin
        ss := FileName + ' wurde nicht heruntergeladen.';
      end;
      Target.Add(ss);
    end;
end;

...

SetLength(tasks, anz);
for i := 0 to anz - 1 do
begin
  fn := Files[i].Filename;
  s := fn + ' wird heruntergeladen...';
  line := Memo1.Lines.Add(s);
  Files[i].Zeilennummer := line;
  tasks[i] := TTask.Create(CreateMyTask(i, fn, CreateResultHandler(Memo1.Lines)));
  tasks[i].Start;
end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.144 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: TTask & Synchronize Verständnisproblem

  Alt 19. Apr 2017, 14:06
Oder eher nicht...

Ok, der ThreadPool managed nur so viele gleichzeitige Thread wie es für die CPU - Core Anzahl sinnvoll ist, aber ist das auch sinnvoll für einen download?

i.d.R. nicht...

Hier würde ich die Anzahl begrenzen.
Das geht nicht über den Threadpool.

Mavarik
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#6

AW: TTask & Synchronize Verständnisproblem

  Alt 19. Apr 2017, 15:37
aber ist das auch sinnvoll für einen download?
Threads die primär IO-Operationen ausführen sind tatsächlich immer recht kritisch zu sehen. Zumindest ist deren Verhalten im Hinblick auf Performance deutlich abweichend zu CPU-lastigen Threads. Muss man denke ich individuell betrachten.

Hier würde ich die Anzahl begrenzen.
Das geht nicht über den Threadpool.
Doch doch, man kann die maximale Threadanzahl einstellen, oder sich sogar einen custom ThreadPool erzeugen, der dann dediziert nur für eine spezielle Art von Tasks verwendet werden kann
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.144 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: TTask & Synchronize Verständnisproblem

  Alt 19. Apr 2017, 16:50
Doch doch, man kann die maximale Threadanzahl einstellen, oder sich sogar einen custom ThreadPool erzeugen, der dann dediziert nur für eine spezielle Art von Tasks verwendet werden kann
Ja, aber Achtung:

Zitat von System.Threading.pas:
Delphi-Quellcode:
function TThreadPool.SetMaxWorkerThreads(Value: Integer): Boolean;
begin
  Result := Value >= TThread.ProcessorCount;
  if Result then
    TInterlocked.Exchange(FMaxLimitWorkerThreadCount, Value);
end;
Mavarik
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#8

AW: TTask & Synchronize Verständnisproblem

  Alt 19. Apr 2017, 22:03
Ja, aber Achtung:

Zitat von System.Threading.pas:
Delphi-Quellcode:
function TThreadPool.SetMaxWorkerThreads(Value: Integer): Boolean;
begin
  Result := Value >= TThread.ProcessorCount;
  if Result then
    TInterlocked.Exchange(FMaxLimitWorkerThreadCount, Value);
end;
Das ist ja echt eine blöde Limitierung
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: TTask & Synchronize Verständnisproblem

  Alt 20. Apr 2017, 08:27
Warum sollte man denn das Maximum geringer setzen wollen als die Anzahl der CPU Kerne?

Wenn man weiß, dass eine Aktion z.B. die Festplatte sehr stark beansprucht, ist ein Threadpool eher nicht geeignet, weil man dann ja gar nicht viele Tasks parallel möchte.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#10

AW: TTask & Synchronize Verständnisproblem

  Alt 20. Apr 2017, 08:48
Warum sollte man denn das Maximum geringer setzen wollen als die Anzahl der CPU Kerne?
Weil man das System nicht komplett auslasten will?
$2B or not $2B
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 19:41 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