多线程 – AsyncCall与Delphi 2007

前端之家收集整理的这篇文章主要介绍了多线程 – AsyncCall与Delphi 2007前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我基本上想要的是启动 AsyncCall,继续我的代码加载.我有接口部分消耗大量的时间(600 ms),我想加载这个代码在独立线程.

我试图使用AsyncCall来做这样的事情:

  1. procedure Load;
  2. begin
  3. ...
  4. end;
  5.  
  6. initialization
  7. AsyncCall(@Load,[]); // or LocalAsyncCall(@Load)

但是,此Load过程实际上在主线程中启动,而不是在新创建的线程中.如何强制Load过程加载到MainThread以外的任何线程?

我可以创建TThread并执行这个,但是我想强制AsyncCall或LocalAsyncCall或任何来自AsyncCall库的工作.

谢谢你的帮助.

解决方法

问题是您的代码不保留由AsyncCall函数返回的IAsyncCall接口.
  1. AsyncCall(@Load,[]);
  2. //AsyncCall returns an IAsyncCall interface,//but this code does not take a reference to it

因此,一旦初始化部分完成,返回的接口的引用计数就递减为零.这样就释放了实现这样做的接口的对象:

  1. destructor TAsyncCall.Destroy;
  2. begin
  3. if FCall <> nil then
  4. begin
  5. try
  6. --> FCall.Sync; // throw raised exceptions here
  7. finally
  8. FCall.Free;
  9. end;
  10. end;
  11. inherited Destroy;
  12. end;

关键是调用Sync来强制异步调用被执行完成.所有这一切都发生在主线程中,它解释了你报告的行为.

解决方案是,您只需要将IAsyncCall接口存储在变量中即可.

  1. var
  2. a: IAsyncCall;
  3.  
  4. initialization
  5. a := AsyncCall(@Load,[]);

在真正的代码中,您需要确保在运行任何依赖于Load的代码之前,Load已经完成.当您的程序达到要求加载被调用的位置时,必须在IAsyncCall界面上调用Sync.

所以你可能会写这样的东西.

  1. unit MyUnit;
  2.  
  3. interface
  4.  
  5. procedure EnsureLoaded;
  6.  
  7. implementation
  8.  
  9. uses
  10. AsyncCalls;
  11.  
  12. ....
  13.  
  14. procedure Load;
  15. begin
  16. ....
  17. end;
  18.  
  19. var
  20. LoadAsyncCall: IAsyncCall;
  21.  
  22. procedure EnsureLoaded;
  23. begin
  24. LoadAsyncCall := nil;//this will effect a call to Sync
  25. end;
  26.  
  27. initialization
  28. LoadAsyncCall := AsyncCall(@Load,[]);
  29.  
  30. end.

从需要加载运行的其他单位调用EnsureLoaded.或者,或者,由MyUnit导出的任何依赖于已运行Load的方法调用EnsureLoaded.后一种选择具有更好的封装.

猜你在找的Java相关文章