我正在尝试找到一种安全/确定的方法来释放封装在OleVariant中的接口。
AFAICS Delphi在程序结束时发布接口引用,但在我的情况下我必须提前完成,因为我必须关闭COM。
procedure Test;
var
LLibrary: OleVariant;
begin
CoInitialize(nil);
try
LLibrary := Null;
try
LLibrary := CreateOleObject(LibraryName);
finally
LLibrary := Unassigned; // <-- I would like to release the interface here
end;
finally
CoUninitialize; // <-- Shutdown of COM
end;
end; // <-- The compiler releases the interface here
我将OleVariant放在一个额外的类实例中,我可以在调用CoUninitialize
之前释放它。
procedure Test;
var
Container: TLibraryContainer; // Holds the OleVariant
begin
CoInitialize(nil);
try
Container := TLibraryContainer.Create;
try
{...}
finally
Container.Free;
end;
finally
CoUninitialize;
end;
end;
这个解决方案是安全的还是我忽略了一个更好的解决方案?
答案 0 :(得分:9)
编译器显然使用隐式本地接口变量作为CreateOleObject
的返回值。然后在例程结束时释放,对你来说太迟了。
有几种方法可以打败这个。首先,您可以明确IDispatch
返回的CreateOleObject
接口引用。这允许您控制其生命周期。
procedure Test;
var
intf: IDispatch;
LLibrary: OleVariant;
begin
CoInitialize(nil);
try
intf := CreateOleObject(LibraryName);
try
LLibrary := intf;
finally
VarClear(LLibrary);
intf := nil;
end;
finally
CoUninitialize;
end;
end;
另一种方法是将调用CreateOleObject
的代码移动到具有自己范围的单独例程中。
procedure DoWork;
var
LLibrary: OleVariant;
begin
LLibrary := CreateOleObject(LibraryName);
//do stuff with LLibrary
end;
procedure Test;
begin
CoInitialize(nil);
try
DoWork;
finally
CoUninitialize;
end;
end;
由于隐式本地引用属于DoWork
范围,因此它会在DoWork
结束时发布,因此在您运行CoUninitialize
之前。
我的建议是使用更清晰的第二个选项,并强制编译器代表您完成工作。