[基本原理]
我们使用一个引用计数可以很简单的完成这一需求。
- 在触发异步操作时,将此计数加 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;
[进一步的实现]
上面的实现简单可靠,唯一的问题,就是对象释放必需等待异步操作完成。这个时间点是不可靠的,要更好的实现可以将异步调用进行额外的处理,并将其与对象的生命周期进行拦截。