Dun*_*can 5 delphi web-services memory-management windows-messages
新手问题:我有一个表单应用程序.它有一个单独的线程,它进行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;
Run Code Online (Sandbox Code Playgroud)
Remote.Run.GetSystemProbeValues函数具有以下原型:
function GetSystemProbeValues : TCWProbeValues; stdcall;
Run Code Online (Sandbox Code Playgroud)
TCWProbeValues是一个TCWProbeValue对象的动态数组(都来自TRemotable).
在我的主要表单中,我收到消息就好并将LParam强制转换回TCWProbeValues:
procedure TFrmCWMain.OnAPIEvent(var msg: TMessage);
begin
ProbeValues := TCWProbeValues(msg.LParam);
end;
Run Code Online (Sandbox Code Playgroud)
我的问题是,动态数组及其对象是由Delphi HTTORIO系统创建的,谁负责释放它们?在我的OnTimer函数返回后,Delphi是否认为内存可重用?(在这种情况下,我的主要形式消息处理程序实际上可以读取消息的LParam引用的内存吗?)或者更确切地说,我是否有责任释放HTTPRIO请求自动实例化的对象?
非常感谢,如果以上需要更多细节/代码,请大声说出来,我会加入它!
干杯,邓肯
TRemotable通过其属性提供生命周期管理DataContext,因此 SOAP 运行时将释放该对象本身。只要数据上下文对象存在,它分配的所有内容也将存在。如果您想声明对某个对象的所有权和责任,只需清除其DataContext财产即可。(在这种情况下,这可能是您想要做的,因为您的 API 事件消息可能会在 SOAP 事件终止后得到处理。)
代码中的问题是您通过发布的消息传递动态数组。当您的OnTimer过程返回到其调用者时,所引用的动态数组的SystemProbeValues引用计数将减少。如果另一个线程尚未处理该消息(而且可能还没有),那么当它确实处理该消息时,动态数组可能已经被销毁。
解决这个问题的简单方法是清除计时器事件处理程序中的引用而不减少引用计数,然后在消息处理程序中执行相反的操作。发布消息后,清除变量:
LParam(SystemProbeValues) := 0;
Run Code Online (Sandbox Code Playgroud)
在消息处理程序中,清除全局ProbeValues变量的旧值并分配新值,如下所示:
ProbeValues := nil;
LParam(ProbeValues) := Msg.LParam;
Run Code Online (Sandbox Code Playgroud)
TTimer代码中潜伏的另一个问题可能是在非 VCL 线程中使用。该类创建一个窗口句柄以在该类的所有实例之间共享。除非您的计时器线程是程序中唯一使用 的线程TTimer,否则您可能会遇到问题,要么函数在错误的线程中运行,要么函数根本不运行。TTimer您可以使用手动SetTimer创建操作系统计时器,或者创建可等待计时器,这可能更适合在不需要保持响应用户操作的线程中使用。