私がやりたいこと:
ジェネリックリストにいくつかのオブジェクトがあります。このオブジェクトのそれぞれを匿名メソッドでキャプチャし、このメソッドを個別のOTLタスクとして実行したいと思います。
これは単純化された例です。
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.
そしてこれが結果です:
ご覧のとおり、メインスレッドではキャプチャが正常に機能しているようです。しかし、オブジェクトへのポインタがキャプチャされたのか、それともそのIDフィールドのみがキャプチャされたのかわかりません。
オブジェクトをキャプチャして匿名メソッドをCreateTask
関数に渡そうとすると、物事がおかしくなります。
まず第一に、の3番目のインスタンスだけTMyObject
がキャプチャされたように見えました。次に、汎用リストにオブジェクトが3つしかないにもかかわらず、コンソールログに4つのメッセージがあります。2番目の動作には一貫性がなく、コンソールに3つのメッセージが表示されることもあれば、4つのメッセージが表示されることもあります。
上記の2つの問題の理由を説明し、問題を排除し、オブジェクトの各インスタンスを個別のOTLタスクに渡すことができるソリューションを提案してください。TThread
(通常のクラスは使いたくないです。)