[教程]如何保证对象释放时,异步调用过程都已经完成

[基本原理]

我们使用一个引用计数可以很简单的完成这一需求。

  • 在触发异步操作时,将此计数加 1;
  • 在异步操作执行完成时,将此计数减 1;
  • 在对象释放前,检查这个计数是否为0,如果不为0,则等待计数变为0。

[实现细节]

type
   TTestObject=class
   private
     FAsyncRefCount:Integer;
     procedure DoAsync;
   public
     destructor Destroy;override;
   end;
...

procedure TTestObject.DoAsync;
begin
  Inc(FAsyncRefCount);
  TThread.ForceQueue(nil,
    procedure
    begin
      Dec(FAsyncRefCount);
      ...
    end);
end;

destructor TTestObject.Destroy;
begin
  //在此检查,保证异步调用完成才真正释放
  while FAsyncRefCount>0 do
    CheckSynchronize(0);
  ...
  inherited;
end;

[进一步的实现]

上面的实现简单可靠,唯一的问题,就是对象释放必需等待异步操作完成。这个时间点是不可靠的,要更好的实现可以将异步调用进行额外的处理,并将其与对象的生命周期进行拦截。

分享到: