Delphi 太早发布界面
Delphi releases interface too soon
我有一个 Delphi client/server 项目,它使用 RemObjects 在客户端和服务器之间进行通信。在 remobject 中定义了服务器和 public 服务函数并为其生成了接口。在某些时候,我们需要从另一个服务调用其他服务。为了做到这一点,我们创建了 class methods/functions,传递当前数据库连接和 remobjects 会话,调用所需函数的实现。例如:
class function TMyService.GetFoo(session: TROSession; conn: Connection): AnsiString;
var
svc: TMyService;
begin
svc := TMyService.Create(nil);
try
IROObjectActivation(svc).OnActivate(session.SessionID, nil);
try
Result := svc.GetFooImpl();
finally
IROObjectActivation(svc).OnDeactivation(session.SessionID);
end;
finally
FreeAndNil(svc);
end;
end;
有时,看起来是随机的,svc 似乎在 FreeAndNil 调用之前已经被释放,这会导致访问冲突。
此时,TMyService 也有一个生成的接口 IMyService,但这只包含 public 方法,而不包含实现。这就是为什么我们使用类型而不是接口来定义 svc
变量的原因。
据我所知,接口对象应该在方法结束时释放,而不是中途释放。是否有任何可以影响此行为的编译器优化?
[编辑]
对了,这个项目里也编译了FastMM4,可能对这个有一些影响。
使用 Delphi 10.3
编译的项目
如果TMyService
支持接口,而你有过早释放的问题,那说明TMyService
class是引用计数class(换句话说,它支持接口,但引用计数未禁用)。
在这种情况下,您需要将此类对象实例存储在接口引用中以正确初始化引用计数。另外你不应该手动释放这样的对象,因为它的内存会被自动管理,如果你需要访问一些没有通过接口公开的方法,你可以通过类型转换来实现。
但是,使用未通过接口公开的方法可能会滥用 class。通常,接口包含所有要使用的方法。
class function TMyService.GetFoo(session: TROSession; conn: Connection): AnsiString;
var
svc: IMyService;
begin
svc := TMyService.Create(nil);
IROObjectActivation(svc).OnActivate(session.SessionID, nil);
try
Result := svc.GetFooImpl();
// or
Result := TMyService(svc).GetFooImpl();
finally
IROObjectActivation(svc).OnDeactivation(session.SessionID);
end;
end;
是否需要为 IROObjectActivation
使用类型转换取决于 IMyService
的声明。可能你不需要 IMyService 接口,你可以只使用 IROObjectActivation
.
我有一个 Delphi client/server 项目,它使用 RemObjects 在客户端和服务器之间进行通信。在 remobject 中定义了服务器和 public 服务函数并为其生成了接口。在某些时候,我们需要从另一个服务调用其他服务。为了做到这一点,我们创建了 class methods/functions,传递当前数据库连接和 remobjects 会话,调用所需函数的实现。例如:
class function TMyService.GetFoo(session: TROSession; conn: Connection): AnsiString;
var
svc: TMyService;
begin
svc := TMyService.Create(nil);
try
IROObjectActivation(svc).OnActivate(session.SessionID, nil);
try
Result := svc.GetFooImpl();
finally
IROObjectActivation(svc).OnDeactivation(session.SessionID);
end;
finally
FreeAndNil(svc);
end;
end;
有时,看起来是随机的,svc 似乎在 FreeAndNil 调用之前已经被释放,这会导致访问冲突。
此时,TMyService 也有一个生成的接口 IMyService,但这只包含 public 方法,而不包含实现。这就是为什么我们使用类型而不是接口来定义 svc
变量的原因。
据我所知,接口对象应该在方法结束时释放,而不是中途释放。是否有任何可以影响此行为的编译器优化?
[编辑] 对了,这个项目里也编译了FastMM4,可能对这个有一些影响。 使用 Delphi 10.3
编译的项目如果TMyService
支持接口,而你有过早释放的问题,那说明TMyService
class是引用计数class(换句话说,它支持接口,但引用计数未禁用)。
在这种情况下,您需要将此类对象实例存储在接口引用中以正确初始化引用计数。另外你不应该手动释放这样的对象,因为它的内存会被自动管理,如果你需要访问一些没有通过接口公开的方法,你可以通过类型转换来实现。
但是,使用未通过接口公开的方法可能会滥用 class。通常,接口包含所有要使用的方法。
class function TMyService.GetFoo(session: TROSession; conn: Connection): AnsiString;
var
svc: IMyService;
begin
svc := TMyService.Create(nil);
IROObjectActivation(svc).OnActivate(session.SessionID, nil);
try
Result := svc.GetFooImpl();
// or
Result := TMyService(svc).GetFooImpl();
finally
IROObjectActivation(svc).OnDeactivation(session.SessionID);
end;
end;
是否需要为 IROObjectActivation
使用类型转换取决于 IMyService
的声明。可能你不需要 IMyService 接口,你可以只使用 IROObjectActivation
.