我基本上想要的是启动
AsyncCall,继续我的代码加载.我有接口部分消耗大量的时间(600 ms),我想加载这个代码在独立线程.
我试图使用AsyncCall来做这样的事情:
procedure Load; begin ... end; initialization AsyncCall(@Load,[]); // or LocalAsyncCall(@Load)
但是,此Load过程实际上在主线程中启动,而不是在新创建的线程中.如何强制Load过程加载到MainThread以外的任何线程?
我可以创建TThread并执行这个,但是我想强制AsyncCall或LocalAsyncCall或任何来自AsyncCall库的工作.
谢谢你的帮助.
解决方法
问题是您的代码不保留由AsyncCall函数返回的IAsyncCall接口.
AsyncCall(@Load,[]); //AsyncCall returns an IAsyncCall interface,//but this code does not take a reference to it
因此,一旦初始化部分完成,返回的接口的引用计数就递减为零.这样就释放了实现这样做的接口的对象:
destructor TAsyncCall.Destroy; begin if FCall <> nil then begin try --> FCall.Sync; // throw raised exceptions here finally FCall.Free; end; end; inherited Destroy; end;
关键是调用Sync来强制异步调用被执行完成.所有这一切都发生在主线程中,它解释了你报告的行为.
解决方案是,您只需要将IAsyncCall接口存储在变量中即可.
var a: IAsyncCall; initialization a := AsyncCall(@Load,[]);
在真正的代码中,您需要确保在运行任何依赖于Load的代码之前,Load已经完成.当您的程序达到要求加载被调用的位置时,必须在IAsyncCall界面上调用Sync.
所以你可能会写这样的东西.
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.
从需要加载运行的其他单位调用EnsureLoaded.或者,或者,由MyUnit导出的任何依赖于已运行Load的方法调用EnsureLoaded.后一种选择具有更好的封装.