What I want to do:
I have a few objects in a genric list. I want to capture each of this object in anonymous method and execute this method as a separate OTL Task.
This is a simplified example:
program Project51;
{$APPTYPE CONSOLE}
uses
SysUtils, Generics.Collections, OtlTaskControl, OtlTask;
type
TProc = reference to procedure;
type
TMyObject = class(TObject)
public
ID: Integer;
constructor Create(AID: Integer);
end;
constructor TMyObject.Create(AID: Integer);
begin
ID := AID;
end;
var
Objects: TList<TMyObject>;
LObject: TMyObject;
MyProc: TProc;
begin
Objects := TList<TMyObject>.Create;
Objects.Add(TMyObject.Create(1));
Objects.Add(TMyObject.Create(2));
Objects.Add(TMyObject.Create(3));
for LObject in Objects do
begin
//This seems to work
MyProc := procedure
begin
Writeln(Format('[SameThread] Object ID: %d',[LObject.ID]));
end;
MyProc;
//This doesn't work, sometimes it returns 4 lines in console!?
CreateTask(
procedure(const Task: IOmniTask)
begin
Writeln(Format('[Thread %d] Object ID: %d',[Task.UniqueID, LObject.ID]));
end
).Unobserved.Run;
end;
Sleep(500); //Just wait a bit for tasks to finish
Readln;
end.
And this is the result:
As you can see, capturing seems to work fine in the main thread. However, I do not know if a pointer to an object has been captured or only its ID field?
When I try to capture the object and pass the anonymous method to CreateTask
function things become weird.
First of all, only the third instance of TMyObject
seemed to be captured. Second of all, I've got four messages in console log despite the fact that I have only three objects in generic list. The second behaviour is inconsistent, sometimes I've got three messages in console, sometimes I've got four.
Please explain me the reason for two issues mentioned above and propose a solution that eliminates the problem and allows me to pass each instance of object to a separate OTL task. (I do not want to use regular TThread
class.)