运行以下代码时,我得到E2555 Cannot capture symbol 'Self'
。
type
TLookupTable = record
FData: TArray<TOtherRec>;
procedure ReverseLeftToRight;
end;
procedure TLookupTable.ReverseLeftToRight;
begin
Parallel.For(0, Length(FData)-1).NoWait.Execute(procedure(i: integer) begin
FData[i]:= FData[i].ReverseLeftRight;
end); {for i}
end;
该如何解决?
答案 0 :(得分:0)
问题是var
参数(包括Self
的隐藏var参数)没有被捕获。但是,我们不想复制该记录,这将是无用的,因为那样我们的方法将无法工作。
使隐藏的self
参数明确的技巧。
如果这是一个类,那么很容易(var S:= Self
),否则,就必须声明一个指向记录的指针。
procedure TLookupTable.ReverseLeftToRight;
type
PLookupTable = ^TLookupTable;
var
S: PLookupTable;
begin
S:= @Self;
Parallel.For(0, Length(FData)-1).NoWait.Execute(procedure(i: integer) begin
S.FData[i]:= S.FData[i].ReverseLeftRight;
end); {for i}
end;
现在,编译器不再抱怨。
(请注意,我正在对S^.xyz
使用隐式语法)。
Delphi Rio
使用如下所示的内联var声明不起作用。
//S: PLookupTable;
begin
var S:= @Self; //inline declaration
Parallel.For(0, Length(FData)-1).NoWait.Execute(procedure(i: integer) begin
S.FData[i]:= S.FData[i].ReverseLeftRight;
end); {for i}
这将生成:E2018 Record, object or class type required
。
我猜内联@Self
被解析为通用指针,这很可惜,因为有足够的信息来推断内联变量的正确类型。
异步问题
如果使用异步(.NoWait
)线程/任务执行代码,则最好将FData
放在本地变量中。作为动态数组的FData已经是一个指针(因此不会进行复制,而只是引用计数)。而且动态数组没有写时复制语义,因此原始数组将得到更新。
照原样,Self
记录可能在代码运行时超出范围,从而导致访问冲突(或更糟)。