Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling of local variable in anonymous procedure passed to TThread.Queue

I have a program which uses a Thread that performs some work. The thread should notify another thread (in this example the main thread) of the progress.

If I use Synchronize() to perform the synchronization everything works as expected. If I synchronize with the main thread and publish the for-variable and put it into a list every single value get's printed correctly into my ListBox:

procedure TWorkerThread.Execute;
var
  i: Integer;
begin
  inherited;

  for i := 1 to 1000 do
  begin
    Synchronize(
      procedure()
      begin
        FireEvent(i);
      end);
  end;
end;

Output: 1, 2, 3, 4, 5 ... 1000

If I use Queue() to perform the synchronization the output is not as expected:

procedure TWorkerThread.Execute;
var
  i: Integer;
begin
  inherited;

  for i := 1 to 1000 do
  begin
    Queue(
      procedure()
      begin
        FireEvent(i);
      end);
  end;
end;

Output: 200, 339, 562, 934, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, [...]

What's happening here? As of my understanding the anonymous procedure should capture the variable "i"?

like image 246
Ranga B. Avatar asked Feb 17 '17 14:02

Ranga B.


1 Answers

The anonymous procedure captures the variable reference. This means that the value is undetermined when the anonymous procedure runs.

In order to capture a value, you will have to wrap it into a unique frame like this:

Type
  TWorkerThread = class (TThread)
    ...
    function GetEventProc(ix : Integer): TThreadProcedure;
  end;

function TWorkerThread.GetEventProc(ix : Integer) : TThreadProcedure;
// Each time this function is called, a new frame capturing ix 
// (and its current value) will be produced.
begin
  Result := procedure begin FireEvent(ix); end;
end;

procedure TWorkerThread.Execute;
var
  i: Integer;
begin
  inherited;

  for i := 1 to 1000 do
  begin
    Queue( GetEventProc(i));
  end;
end;

See also Anonymous methods - variable capture versus value capture.

like image 100
LU RD Avatar answered Oct 08 '22 00:10

LU RD