Processing a local variable in an anonymous procedure is passed to TThread.Queue

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

If I use Synchronize () to do the synchronization, everything works as expected. If I synchronize with the main thread and publish for-variable and put it on the list, each value will be correctly printed in 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 do 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 going on here? As far as I understand, an anonymous procedure should fix the variable "i"?

+5
source share
1 answer

An anonymous procedure captures a reference to a variable. This means that the value is not defined when an anonymous procedure is executed.

To fix the value, you have to wrap it in a unique frame as follows:

 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 - Capturing a Variable and Capturing a Value .

+5
source

Source: https://habr.com/ru/post/1264349/


All Articles