2016-05-15 1 views
3

Comment utiliser correctement la boucle dans un TTask? Je continue d'obtenir seulement le dernier élément de ListBox1 dans le mémo, par exemple si j'ai 5 éléments dans ListBox1, je reçois le dernier élément de ListBox1 5 fois dans memo1!, quel est le problème avec le code?Comment utiliser pour la boucle à l'intérieur d'un thread de thread TTin delphi 10

var 
    i: Integer; 
    lPath: string; 
begin 
    for i := 0 to ListBox1.Items.Count - 1 do 
    begin 
    lPath := ListBox1.Items.Strings[i]; 
    TTask.Create(
     procedure 
     var 
     lHTTP: TIdHTTP; 
     IdSSL: TIdSSLIOHandlerSocketOpenSSL; 
     begin 
     lHTTP := TIdHTTP.Create(nil); 

     TThread.Synchronize(nil, 
      procedure 
      begin 
      Form1.Caption := 'Task Running...'; 
      end 
     ); 

     try 
      lHTTP.ReadTimeout := 30000; 
      lHTTP.HandleRedirects := True; 
      IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(lHTTP); 
      IdSSL.SSLOptions.Method := sslvTLSv1; 
      IdSSL.SSLOptions.Mode := sslmClient; 
      lHTTP.IOHandler := IdSSL; 
     Finally 
      try 
      lHTTP.Get('http://website.com/'+lPath, TStream(nil)); 
      Finally 
      lHTTP.Free; 
      end; 
     end; 

     TThread.Synchronize(nil, 
      procedure 
      begin 
      Memo1.Lines.Add(lPath); 
      end 
     ); 

     end 
    ).Start; 

    end; 
end; 
+0

@Phil: Cela n'a rien à voir avec OTL. C'est la nouvelle fonctionnalité de traitement parallèle dans Delphi 10 Seattle/Berlin. –

+0

il pourrait être, mais je ne sais pas comment l'appliquer à mon code @PhilRoss – ColdZer0

Répondre

3

Voici le code adapté:

// Current method: 
procedure TMyForm.XYZ 
var 
    i: Integer; 
    lPath: string; 
begin 
    for i := 0 to ListBox1.Items.Count - 1 do 
    begin 
    lPath := ListBox1.Items.Strings[i]; 
    StartDownloadTask(lPath); 
    end; 
end; 

// Put task creation in separate method: 
procedure TMyForm.StartDownloadTask(lPath: string) 
begin 
    TTask.Create(
     procedure 
     var 
     lHTTP: TIdHTTP; 
     IdSSL: TIdSSLIOHandlerSocketOpenSSL; 
     begin 
     lHTTP := TIdHTTP.Create(nil); 

     TThread.Synchronize(nil, 
      procedure 
      begin 
      Form1.Caption := 'Task Running...'; 
      end 
     ); 

     try 
      lHTTP.ReadTimeout := 30000; 
      lHTTP.HandleRedirects := True; 
      IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(lHTTP); 
      IdSSL.SSLOptions.Method := sslvTLSv1; 
      IdSSL.SSLOptions.Mode := sslmClient; 
      lHTTP.IOHandler := IdSSL; 
     Finally 
      try 
      lHTTP.Get('http://website.com/'+lPath, TStream(nil)); 
      Finally 
      lHTTP.Free; 
      end; 
     end; 

     TThread.Synchronize(nil, 
      procedure 
      begin 
      Memo1.Lines.Add(lPath); 
      end 
     ); 

     end 
    ).Start; 
end; 

Pour une explication sur l'arrière-plan voir l'explication dans https://stackoverflow.com/a/13349520/101087

parties les plus importantes de l'autre réponse:

Remarque cette capture de variables capture des variables et non des valeurs. Si une valeur de la variable change après avoir été capturée en construisant une méthode anonyme , la valeur de la variable la méthode anonyme capturée change également, car ils sont la même variable avec le même stockage .

Pour capturer la valeur de la variable de boucle, envelopper la création de la tâche dans une fonction distincte:

+0

Vous le vrai MVP m8 – ColdZer0