0

Both constructs in the below code give error E2555 Cannot capture symbol WriteToXMLFile

Why is that?

I had a similar warning when I tried to use AParameter in the anonymous proc, and solved it by using a local 'lParameter := AParameter', so I thought a local proc would work as well....

Since WriteToXMLFile contains code I do no want to replicate, where is the proper location to define it?

procedure DoStuff(AParameter: Integer);

   procedure WriteToXMLFile;
   begin
      // ...
   end;

begin
  (* 1 *)
  if GetCurrentThreadID= MainThreadID then
    WriteToXMLFile
  else
    TThread.Synchronize(nil,WriteToXMLFile);

  (* 2 *)
  if GetCurrentThreadID= MainThreadID then
    WriteToXMLFile
  else
    TThread.Synchronize(nil,procedure
                begin
                   WriteToXMLFile;
                end);
end;
Jan Doggen
  • 8,799
  • 13
  • 70
  • 144
  • FYI, there is no need to check for `GetCurrentThreadID = MainThreadID` manually, as `TThread.Synchronize()` handles that internally for you. You can call `Synchronize()` unconditionally regardless of the calling thread. – Remy Lebeau Mar 18 '20 at 19:01

1 Answers1

1

Using nested procedures in anonymous methods is not supported by the compiler.

Instead, change the nested procedure to an anonymous method in this way:

procedure DoStuff(AParameter: Integer);

   function CaptureWriteToXMLFile : TThreadProcedure;
   begin
     Result :=
       procedure
       begin
         // Code here ...
       end;
   end;
var
  WriteToXMLFile : TThreadProcedure;
begin
  WriteToXMLFile := CaptureWriteToXMLFile();

  if GetCurrentThreadID= MainThreadID then
    WriteToXMLFile
  else
    TThread.Synchronize(nil,WriteToXMLFile);
end;

The anonymous function returns a TThreadProcedure. A local variable is assigned a resulting anonymous method, which can be passed as a parameter to the Syncronize procedure.

LU RD
  • 34,438
  • 5
  • 88
  • 296
  • *TThreadProcedure = reference to procedure;* A wondrous new animal in my vocabulary – Jan Doggen Mar 18 '20 at 12:12
  • Surprisingly, I get an *E2010 incompatible types: TThreadProcedure and Procedure* if I omit the (): *WriteToXMLFile := CaptureWriteToXMLFile*. – Jan Doggen Mar 18 '20 at 12:25
  • Yes, the extra parenthesis is needed to get the compiler to understand. – LU RD Mar 18 '20 at 12:27
  • 1
    See also [How to assign a function, returned by another function, to a function variable? The result rather than the generating function itself](https://stackoverflow.com/a/21246321/576719) for an explanation of the parenthesis. – LU RD Mar 18 '20 at 12:42