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