我在genric列表中有一些对象.我想以匿名方法捕获每个对象,并将此方法作为单独的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类.)
解决方法
Note that variable capture captures variables—not values. If a variable’s value changes after being captured by constructing an anonymous method,the value of the variable the anonymous method captured changes too,because they are the same variable with the same storage.
在您的代码中,只有一个LObject变量,因此您构造的所有匿名方法都会引用它.随着循环的进展,LObject的值会发生变化.这些任务还没有机会开始运行,所以当它们最终运行时,循环终止并且LObject有它的最终值.形式上,循环后最终值未定义.
要捕获循环变量的值,请将任务的创建包装在单独的函数中:
function CreateItemTask(Obj: TMyObject): TOmniTaskDelegate; begin Result := procedure(const Task: IOmniTask) begin Writeln(Format('[Thread %d] Object ID: %d',Obj.ID])); end; end;
然后更改循环代码:
CreateTask(CreateItemTask(LObject)).Unobserved.Run;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。