加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

多线程 – AsyncCall与Delphi 2007

发布时间:2020-12-14 16:23:28 所属栏目:Java 来源:网络整理
导读:我基本上想要的是启动 AsyncCall,继续我的代码加载.我有接口部分消耗大量的时间(600 ms),我想加载这个代码在独立线程. 我试图使用AsyncCall来做这样的事情: procedure Load;begin...end;initialization AsyncCall(@Load,[]); // or LocalAsyncCall(@Load)
我基本上想要的是启动 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.后一种选择具有更好的封装.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读