Iva*_*ark 11 delphi multithreading asynchronous delphi-2007
我基本上想要的是启动AsyncCall并继续我的代码加载.我有接口部分,消耗大量的时间(600 + ms),我想在独立的线程中加载此代码.
我试图用AsyncCall
这样的东西:
procedure Load;
begin
...
end;
initialization
AsyncCall(@Load, []); // or LocalAsyncCall(@Load)
Run Code Online (Sandbox Code Playgroud)
但是,此Load
过程实际上是在主线程中启动,而不是在新创建的线程中启动.如何强制将Load
程序加载到除以外的任何线程中MainThread
?
我可以创建TThread
和Execute
这个,但我想强制AsyncCall
或LocalAsyncCall
或任何从AsyncCall
库中进行工作.
谢谢你的帮助.
你尝试过这样的事吗?:
procedure Load;
begin
if GetCurrentThreadId <> MainThreadID then
Beep;
end;
var a: IAsyncCall;
initialization
a := AsyncCall(@Load, []);
a.ForceDifferentThread;
Run Code Online (Sandbox Code Playgroud)
ForceDifferentThread()告诉AsyncCalls,不能在当前线程中执行分配的函数.
问题是您的代码没有保留函数IAsyncCall
返回的接口AsyncCall
.
AsyncCall(@Load, []);
//AsyncCall returns an IAsyncCall interface,
//but this code does not take a reference to it
Run Code Online (Sandbox Code Playgroud)
因此,一旦初始化部分完成,返回的接口的引用计数就会减少到零.因此,这释放了实现此接口的对象:
destructor TAsyncCall.Destroy;
begin
if FCall <> nil then
begin
try
--> FCall.Sync; // throw raised exceptions here
finally
FCall.Free;
end;
end;
inherited Destroy;
end;
Run Code Online (Sandbox Code Playgroud)
关键行是Sync
强制异步调用执行完成的调用.所有这些都发生在主线程中,它解释了您报告的行为.
解决方案是您只需将IAsyncCall
接口存储在变量中即可使接口保持活动状态.
var
a: IAsyncCall;
initialization
a := AsyncCall(@Load, []);
Run Code Online (Sandbox Code Playgroud)
在实际代码中,您需要确保Load
在运行任何依赖的代码之前已完成Load
.当你的程序的地步了需要它Load
已被称为它调用Sync
的上IAsyncCall
界面.
所以你可能会写这样的东西.
unit MyUnit;
interface
procedure EnsureLoaded;
implementation
uses
AsyncCalls;
....
procedure Load;
begin
....
end;
var
LoadAsyncCall: IAsyncCall;
procedure EnsureLoaded;
begin
LoadAsyncCall := nil;//this will effect a call to Sync
end;
initialization
LoadAsyncCall := AsyncCall(@Load, []);
end.
Run Code Online (Sandbox Code Playgroud)
EnsureLoaded
来自其他需要Load
运行的单位的电话.或者,也可以EnsureLoaded
从MyUnit
依赖于Load
运行的任何方法调用.后一种选择有更好的封装.