1

我有一个运行长时间操作的模型对象。我试图在线程中运行其中一些操作以保持界面响应,一次下载 2 个东西等,但我想尽可能地从界面代码中隐藏这些细节。我正在尝试使用 AsyncCall 库,但遇到了问题。

type EUpdaterAction = (auFoundCurrentVersion, auFoundUpdateVersion);

type
  TUpdater = class
  public
    procedure loadCurrentVersion();
    procedure notify(action: EUpdaterAction);
  end;

procedure TUpdater.loadCurrentVersion();
begin
  TAsyncCalls.Invoke(procedure 
  begin 
    Assert(Windows.GetCurrentThreadId() <> System.MainThreadID);
    //Really long code
    TAsyncCalls.VCLSync(procedure begin notify(auFoundCurrentVersion); end);
  end);
end;

断言失败。我是否需要做一些事情让它在单独的线程中运行,或者库中显示的第一个示例实际上并没有在线程中运行?

4

2 回答 2

6

您需要调用IAsyncCall.ForceDifferentThread以强制代码在不同的线程中运行。在您的示例中, TAsyncCalls.Invoke() 返回的接口立即释放,因为函数结束并释放 IAsyncCall 接口调用该Sync方法。并且由于您的任务尚未开始,该Sync方法将在同一个线程中执行它,除非该ForceDifferentThread方法被调用。

TAsyncCalls.Invoke(procedure 
begin 
  Assert(Windows.GetCurrentThreadId() <> System.MainThreadID);
  //Really long code
  TAsyncCalls.VCLSync(procedure begin notify(auFoundCurrentVersion); end);
end).ForceDifferentThread; // <<<<<

但这真的是你想要的吗?我猜你想在 loadCurrentVersion() 退出后保持线程处于活动状态。对于这个 AsyncCalls 不是正确的工具。

于 2012-09-08T17:58:18.950 回答
1

这已经在 SO 上讨论过了。当您调用InvokeAsyncCalls 时,会将您的代码放入要执行的队列中;稍后 Asyncalls 会找到一个工作线程来执行您的代码,但是如果您的代码在工作线程分配给您的代码Sync 之前ForceDifferentThread调用(并且没有使用),AsyncCalls 会从队列中删除您的代码并在主线程中执行它。这是设计使然。

于 2012-09-08T18:28:28.753 回答