parallel.async,传递参数线程安全
parallel.async, pass parameters thread-safe
看看这段(伪)代码
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;
这会产生竞争条件,因为我很难发现。因为 TestASync
在匿名方法获得调用 MyThreadedPorc
的机会之前已经完成,所以 MyThreadedProc
是用 nil
接口调用的。 (这已经比一些随机值好很多了)
Q1:简单的非引用计数变量(如整数、双精度等)是否也是这种情况 - 我强烈怀疑它们可能会 changed/return 随机值,因为它们位于堆栈上。
Q2:如何以简单、干净的方式解决这个问题?
我一直在摆弄 IOmniTask
接口和其他方法来启动不受监控的后台线程之类的东西,但所有这些似乎都使我的代码变得混乱并使源代码难以理解。
也许是这样的? :
procedure TestGenericASync;
begin
var lSomeIntf:=TSomeImplementor.Create as ISomeIntf;
parallel.ASync<ISomeIntf>(lSomeIntf,
procedure (const aSomeIntf:ISomeIntf)
begin
MyThreadedProc(aSomeIntf);
end
);
end;
As suggested, you have to work around a Delphi bug (RSP-26666) 内联变量声明。匿名方法无法正确捕获这些内联变量声明。
解决方法是不使用内联变量。 (或升级到 RS 10.4 Sydney。)
procedure TestASync;
var lSomeIntf:ISomeIntf; // declaring here works around the bug
begin
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;
看看这段(伪)代码
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;
这会产生竞争条件,因为我很难发现。因为 TestASync
在匿名方法获得调用 MyThreadedPorc
的机会之前已经完成,所以 MyThreadedProc
是用 nil
接口调用的。 (这已经比一些随机值好很多了)
Q1:简单的非引用计数变量(如整数、双精度等)是否也是这种情况 - 我强烈怀疑它们可能会 changed/return 随机值,因为它们位于堆栈上。
Q2:如何以简单、干净的方式解决这个问题?
我一直在摆弄 IOmniTask
接口和其他方法来启动不受监控的后台线程之类的东西,但所有这些似乎都使我的代码变得混乱并使源代码难以理解。
也许是这样的? :
procedure TestGenericASync;
begin
var lSomeIntf:=TSomeImplementor.Create as ISomeIntf;
parallel.ASync<ISomeIntf>(lSomeIntf,
procedure (const aSomeIntf:ISomeIntf)
begin
MyThreadedProc(aSomeIntf);
end
);
end;
As
解决方法是不使用内联变量。 (或升级到 RS 10.4 Sydney。)
procedure TestASync;
var lSomeIntf:ISomeIntf; // declaring here works around the bug
begin
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;