delphi – 在OTL中使用时,如何通过匿名方法捕获变量?
我想做的事:
我在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类.) 解决方法
The documentation describes what’s happening:
在您的代码中,只有一个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; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |