我应该释放从 Web 服务调用自动实例化的 Delphi 对象吗?

5

新手问题:我有一个表单应用程序。它有一个独立的线程,该线程进行 Web 服务调用,然后将调用结果发布到主窗体。

在我的线程中,当经过 X 秒后(使用 TTimer),我调用:

procedure TPollingThread.OnTimer(Sender: TObject);
var
SystemProbeValues : TCWProbeValues;  
begin
SystemProbeValues := Remote.Run.GetSystemProbeValues;
PostMessage( ParentHandle, WM_APIEVENT ,Integer(apiMultiCellStatus), Integer(SystemProbeValues) );
end;

函数Remote.Run.GetSystemProbeValues具有以下原型:

function GetSystemProbeValues : TCWProbeValues; stdcall;

TCWProbeValues是一个TCWProbeValue对象的动态数组(所有这些对象都是从TRemotable派生而来)。

在我的主窗体中,我可以成功地接收到该消息并将LParam转换回TCWProbeValues:

procedure TFrmCWMain.OnAPIEvent(var msg: TMessage);
begin
ProbeValues := TCWProbeValues(msg.LParam);
end;

我的问题是,鉴于动态数组及其对象是由Delphi HTTORIO系统创建的,那么谁负责释放它们?Delphi是否考虑在我的OnTimer函数返回后可重用内存? (如果是这种情况,那么我的主表单消息处理程序实际上可以读取消息的LParam引用的内存,这纯粹是好运吗?)还是说,我需要负责释放由HTTPRIO请求自动实例化的对象?非常感谢,请告知上述内容是否需要更多详细信息/代码,我会添加!祝好,邓肯
1个回答

4

TRemotable 通过其 DataContext 属性提供生命周期管理,因此 SOAP 运行时将自动释放该对象。只要数据上下文对象存在,它所分配的所有内容也将存在。如果您想要拥有和对一个对象负责,只需清除其 DataContext 属性即可。(在这种情况下,这可能是您想要做的,因为您的 API 事件消息可能会在 SOAP 事件终止后处理。)


您代码中的一个问题是,您通过已发布的消息传递了一个动态数组。当您的 OnTimer 过程返回到其调用者时,由 SystemProbeValues 引用的动态数组将其引用计数减少。如果另一个线程尚未处理该消息(很可能没有),则动态数组在它开始处理该消息之前就可能已被销毁。
解决这个问题的简单方法是,在定时器事件处理程序中清除变量的引用,而不降低引用计数,然后在消息处理程序中执行相反的操作。在发布消息后,清除变量:
LParam(SystemProbeValues) := 0;

在您的消息处理程序中,清除全局变量ProbeValues的旧值,并像这样分配新值:
ProbeValues := nil;
LParam(ProbeValues) := Msg.LParam;

你的代码中可能存在的另一个问题是在非VCL线程中使用TTimer。该类创建一个窗口句柄,以在所有类实例之间共享。除非你的计时器线程是程序中唯一使用TTimer的线程,否则你可能会遇到问题,要么函数在错误的线程中运行,要么根本不运行。你可以使用SetTimer手动创建操作系统定时器,或者创建一个可等待定时器,这可能更适合在不需要对用户操作保持响应的线程中使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接