【发布时间】:2012-11-01 04:29:15
【问题描述】:
我想做什么:
我在一个通用列表中有一些对象。我想在匿名方法中捕获每个对象,并将该方法作为单独的 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 函数时,事情变得很奇怪。
首先,似乎只捕获了TMyObject 的第三个实例。其次,尽管我在通用列表中只有三个对象,但我在控制台日志中有四条消息。第二种行为不一致,有时我在控制台中收到三个消息,有时我收到四个。
请解释我上面提到的两个问题的原因,并提出一个解决方案来消除这个问题,并允许我将每个对象实例传递给一个单独的 OTL 任务。 (我不想使用常规的TThread 类。)
【问题讨论】:
标签: delphi closures delphi-2009 anonymous-methods omnithreadlibrary