Действительно ли я должен освободить объект Delphi, который автоинстанцируют от вызова веб-сервисов?

Вопрос о новичке: у Меня есть приложение форм. Это имеет отдельный поток, который выполняет вызов веб-сервисов и затем отправляет результаты вызова к основной форме.

В моем потоке, после того, как X секунд передали (использование TTimer), я звоню:

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

Удаленная функция. Выполненный. 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?

Большое спасибо, кричите, если вышеупомянутые потребности больше детали / код и я добавим к нему!

С наилучшими пожеланиями, Duncan

5
задан Duncan 29 March 2010 в 14:29
поделиться

1 ответ

TRemotable обеспечивает управление временем жизни через свойство DataContext, поэтому среда выполнения SOAP сама освободит объект. Пока существует объект data-context, будет существовать и все, что он выделил. Если вы хотите заявить о своем праве собственности и ответственности за объект, просто очистите его свойство DataContext. (Вероятно, именно это вы захотите сделать в данном случае, поскольку ваше сообщение об API-событии может быть обработано после завершения SOAP-события.)


Проблема в вашем коде заключается в том, что вы передаете динамический массив через отправленное сообщение. Когда ваша процедура OnTimer возвращается к своему вызывающему пользователю, динамический массив, на который ссылается SystemProbeValues, будет иметь уменьшенное количество ссылок. Если другой поток еще не обработал сообщение (а он, скорее всего, не обработал), то динамический массив может быть уничтожен к тому времени, когда он доберется до обработки этого сообщения.

Простой способ обойти это - очистить ссылку в обработчике события таймера, не уменьшая счетчик ссылок, а затем сделать обратное в обработчике сообщения. После отправки сообщения очистите переменную:

LParam(SystemProbeValues) := 0;

В обработчике сообщения очистите старое значение глобальной переменной ProbeValues и присвойте новое значение следующим образом:

ProbeValues := nil;
LParam(ProbeValues) := Msg.LParam;

Другая проблема, скрывающаяся в вашем коде, может заключаться в использовании TTimer в потоке, не относящемся к VCL. Этот класс создает хэндл окна для совместного использования всеми экземплярами класса. Если ваш поток таймера не является единственным потоком в программе, использующим TTimer, у вас, вероятно, возникнут проблемы, либо функции будут выполняться не в том потоке, либо не будут выполняться вообще. Вместо TTimer вы можете использовать SetTimer для создания таймера ОС вручную, или вы можете создать waitable timer, который может быть более подходящим для использования в потоке, который не должен реагировать на действия пользователя.

4
ответ дан 15 December 2019 в 00:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: