问题是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 的隐式语法)。
德尔福里约
使用如下所示的内联 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 作为一个动态数组,已经是一个指针(所以不会发生复制,只是一个引用计数)。并且动态数组没有 Copy-on-Write 语义,因此原始数组会得到更新。
照原样,Self 记录可能会在代码运行时超出范围,从而导致访问冲突(或更糟)。