When I run the following code I get 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;
How do I fix this?
The problem is that
varparameters (including hidden var parameters toSelf) do not get captured. However, we do not want to copy the record, that would be useless, because then our method would not work.The trick is to make the hidden
selfparameter explicit.If it's a class, then it's easy (
var S:= Self), if not you'll have to declare a pointer to your record.Now the compiler no longer complains.
(Note that I'm using the implicit syntax for
S^.xyz).Delphi Rio
Using a inline var declaration as shown below, does not work.
This generates:
E2018 Record, object or class type required.I guess the inline
@Selfgets resolved to a generic pointer, which is a shame, because there is enough info to infer the correct type for the inline variable.Asynchronous issues
If you're executing the code using a Async (
.NoWait) thread/task, then it might be better to putFDatain the local variable. FData, being a dynamic array, is already a pointer (so no copying will take place, just a ref count). And dynamic arrays do not have Copy-on-Write semantics, so the original will get updated.As is, the
Selfrecord might go out of scope whilst the code is running, because the pointer operationS:= @Selfdoes not cause the reference count on FData to increase). This might cause an access violation (or worse).Taking a reference to FData causes its refcount to go up, meaning it cannot go out of scope prematurely.