【问题标题】:How to use for loop inside a TTask threadin delphi 10如何在delphi 10的任务线程中使用for循环
【发布时间】:2016-05-15 00:02:15
【问题描述】:

如何在 TTask 中正确使用 for 循环?我一直在备忘录中只得到 ListBox1 的最后一项,例如,如果我在 ListBox1 中有 5 个项目,我在 memo1 中得到 ListBox1 的最后一项 5 次!,代码有什么问题?

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;

【问题讨论】:

  • @Phil:这与 OTL 无关。这是 Delphi 10 Seattle/Berlin 中的新并行处理功能。
  • 它可能是,但我不知道如何将它应用到我的代码@PhilRoss

标签: delphi concurrency delphi-10-seattle ppl-delphi


【解决方案1】:

这里是修改后的代码:

// 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;

背景解释见https://stackoverflow.com/a/13349520/101087中的解释

其他答案中最重要的部分:

请注意,变量捕获捕获的是变量,而不是值。如果一个 变量的值在通过构造一个捕获后发生变化 匿名方法,变量的值匿名方法 也捕获了更改,因为它们是相同的变量,具有相同的 存储。

要捕获循环变量的,包装任务的创建 在一个单独的函数中:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-04
    • 1970-01-01
    • 1970-01-01
    • 2011-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多