delphi 如何在排队的匿名方法中保留变量值[duplicate]

46scxncf  于 2022-11-23  发布在  其他
关注(0)|答案(1)|浏览(182)

此问题在此处已有答案

How the variable capturing in anonymous functions works in Delphi TTask - PPL?(1个答案)
11天前关闭。
给出以下代码:

procedure TForm1.Button1Click(Sender: TObject);
var
  myTask: ITask;
begin

  myTask := TTask.Run(
    procedure
    var
      i: Integer;
    begin
      for i := 0 to 3 do
      begin
        TThread.ForceQueue(
            nil
          , procedure
            begin
              ShowMessage('Count: ' + i.ToString);
            end
        );

        //I know this will work
//        TThread.Synchronize(
//            nil
//          , procedure
//            begin
//              ShowMessage('Count: ' + i.ToString);
//            end
//        );

      end;
    end
  );
end;

这将始终打印“计数:4寸
有没有办法在执行排队的匿名过程时保留变量i
我知道使用Synchronize()可以工作,但我更喜欢使用Queue,因为在我的真实的情况中,queued方法会在文件中写入一些日志。我的任务不需要等待日志,这就是为什么我更喜欢使用Queue()
我用的是 Delphi 10.3。

wxclj1h5

wxclj1h51#

首先,您应该使用TThread.Queue()而不是TThread.ForceQueue()。后者只用于主UI线程,而不是任务线程。
其次,匿名方法捕获变量引用,而不是值。请阅读documentation,特别是“变量绑定机制”一节。您正在排队4个共享单个变量的匿名方法,这就是为什么它们的结果都是相同的值。
要解决这个问题,请将捕获移到另一个过程中,这样匿名方法就不再共享单个变量。例如:

procedure TForm1.Button1Click(Sender: TObject);
var
  myTask: ITask;
begin
  myTask := TTask.Run(
    procedure
    var
      i: Integer;
      procedure DoQueue(Value: Integer);
      begin
        TThread.Queue(
            nil
          , procedure
            begin
              ShowMessage('Count: ' + Value.ToString);
            end
        );
      end;
    begin
      for i := 0 to 3 do
      begin
        DoQueue(i);
      end;
    end
  );
end;

相关问题