You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi(D11) PPL中TTask匿名函数变量捕获异常问题咨询

Delphi PPL 任务输出重复值的原因与解决方法

这是并行编程里特别常见的变量捕获陷阱,你踩的这个坑本质是Delphi匿名函数对外部变量的捕获逻辑——它抓的是变量的引用,不是循环迭代那一刻的具体值。

咱们拆解下你的代码:循环里每次把j := i,然后创建的匿名函数引用了j。但循环跑起来的速度比任务执行快多了,等3秒后任务开始执行SendDebugFmt的时候,整个循环已经跑完,j的最终值是5,所以所有任务输出的都是最后一次的5。

解决这个问题有两种常用方案:


方案1:循环内创建局部变量绑定当前值

在循环内部声明一个局部变量,把当前迭代的i赋值给它,这样每次迭代都会生成一个独立的变量实例,匿名函数捕获的是这个专属的局部变量,就不会和其他任务共享引用了:

procedure TForm2.LaunchTasks;
const cmax = 5;
Var ltask: ITask; i: Integer;
begin
  for i := 1 to cmax do
  begin
    // 每次迭代都会生成一个新的localJ实例
    var localJ := i;
    ltask := TTask.Create(
      procedure ()
      begin
        Sleep(3000);
        SendDebugFmt('Task #%d' ,[localJ])
      end);
    ltask.Start;
  end;
end;

方案2:用TTask.Run的参数传递值

Delphi 11支持TTask.Run的重载方法,你可以直接把当前迭代的i作为参数传递给任务,这样就彻底绕过了变量引用的问题:

procedure TForm2.LaunchTasks;
const cmax = 5;
Var i: Integer;
begin
  for i := 1 to cmax do
  begin
    TTask.Run(procedure(const taskParam: Integer)
      begin
        Sleep(3000);
        SendDebugFmt('Task #%d' ,[taskParam])
      end, i);
  end;
end;

这两种方法的核心都是让每个任务绑定到当前迭代的具体数值,而不是共享同一个变量的引用,这样就能得到你预期的Task #1到Task #5的输出了。

内容的提问来源于stack exchange,提问作者user8934301

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 11:17:33