【发布时间】:2020-09-01 04:44:03
【问题描述】:
看看这个(伪)代码
procedure TestASync;
begin
var lSomeIntf:=TSomeImplementor.Create as ISomeIntf;
parallel.ASync(
procedure
begin
sleep(1000); // allow the main thread to finish
MyThreadedProc(lSomeIntf);
end
);
sleep(100); // will finish before sub-thread
end;
这会产生一个竞争条件,因为我发现很难。因为在匿名方法有机会调用MyThreadedPorc 之前,TestASync 已经完成,所以使用nil 接口调用MyThreadedProc。 (这已经比一些随机值好很多了)
Q1:对于简单的非引用计数变量(如整数、双精度等)是否也是如此 - 我强烈怀疑它们可能会更改/返回随机值,因为它们位于在堆栈上。
Q2:如何以简单、干净的方式解决这个问题?
我一直在摆弄IOmniTask 接口和其他方法来启动类似的不受监控的后台线程,但所有这些似乎都使我的代码变得混乱并使源代码难以理解。
也许是这样的? :
procedure TestGenericASync;
begin
var lSomeIntf:=TSomeImplementor.Create as ISomeIntf;
parallel.ASync<ISomeIntf>(lSomeIntf,
procedure (const aSomeIntf:ISomeIntf)
begin
MyThreadedProc(aSomeIntf);
end
);
end;
【问题讨论】:
-
您的原始代码应该可以工作。捕获内联变量或直接使用该变量作为参数可能存在问题。我会尝试删除内联变量声明并使用常规局部变量,如果这不起作用,则在 Async proc 中声明局部变量并在将其用作参数之前为其分配 lSomeIntf。目前无法测试以了解实际情况。
-
在调用 MyThreadedProc 之前将其分配给匿名过程中的局部变量无效。在匿名程序开始时设置断点,lSOmeIntf 已经为零。 (可能取决于 CPU、速度和随机性。
-
@DalijaPrasnikar 是正确的。 anon 方法由一个类实现,该类引用接口(捕获)并应使其保持活动状态。
-
捕获内联变量有一个错误quality.embarcadero.com/browse/RSP-26666 删除内联变量声明应该可以工作(刚刚检查过),如果没有,那么我们需要查看minimal reproducible example
-
没有竞争条件。在 TestAsync 完成之前捕获变量(这意味着额外增加引用计数)并减少局部变量引用计数。如果您有一些问题,它们不是由于您在此处提供的捕获和代码造成的。
标签: multithreading delphi omnithreadlibrary