Jak mogę przechwytywać zmienne metodą anonimową, gdy używasz ich w OTL?
Co chcę robić:
Mam kilka obiektów na liście genów. Chcę przechwycić każdy z tych obiektów metodą anonimową i wykonać tę metodę jako oddzielne zadanie OTL.
To jest uproszczony przykład:
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.
Oto rezultat:
Jak widać, przechwytywanie wydaje się działać poprawnie w głównym wątku. Nie wiem jednak, czy przechwycono wskaźnik do obiektu, czy tylko jego pole ID?
Kiedy próbuję przechwycić obiekt i przekazać anonimową metodęCreateTask
funkcje stają się dziwne.
Przede wszystkim tylko trzecia instancjaTMyObject
wydawało się, że został schwytany. Po drugie, mam cztery komunikaty w dzienniku konsoli, mimo że mam tylko trzy obiekty na ogólnej liście. Drugie zachowanie jest niespójne, czasami mam trzy wiadomości w konsoli, czasami mam cztery.
Wyjaśnij mi przyczynę dwóch wyżej wymienionych problemów i zaproponuj rozwiązanie, które wyeliminuje problem i pozwoli mi przekazać każdą instancję obiektu do oddzielnego zadania OTL. (Nie chcę używać regularnychTThread
klasa.)