delphi xe2 правильное удаление указателя, созданного из потока, указатель которого отправляется в основной поток

Я хотел бы задать несколько вопросов, позвольте мне сначала объяснить вам, и вы можете увидеть вопросы под этим постом. Я создал многопоточное приложение, которое считывает и обновляет данные из базы данных. Потоки взаимодействуют с основным потоком, используя sendmessage. Я передаю указатель TRecord на sendmessage и размещаю указатель в основном потоке. Ниже приведены фрагменты кода, демонстрирующие структуру процесса:

const WM_MY_MESSAGE = WM_USER + 0;

PTestPointerRecord : ^TTestPointerRecord;
TTestPointerRecord = record
  i : integer;
end;

Вот событие выполнения расширенного класса TThread. Он будет работать непрерывно, пока поток не будет приостановлен или остановлен.

procedure TSampleThreadClass.Execute;
var
  TestPointerRecord : PTestPointerRecord;
  FConnection : TConnectionObject;
  FQuery : TQueryObject;
begin
  while not Terminated do
  begin
    New(PTestPointerRecord);
    FConnection := TConnectionObject.Create(nil);
    FQuery := TQueryObject.Create(nil);
    try
      FConnection.connectionstring := 'path';
      FConnection.loginPrompt := False;
      FConnection.open;

      FQuery.connection := FConnection;
      FQuery.close;
      FQuery.sql.clear;
      FQuery.sql.add('select column1, column2 from table');
      FQuery.open;

      PTestPointerRecord.i := 0;
      SendMessage(frmMain.handle, WM_MY_MESSAGE, 0, integer(PTestPointerRecord));
    finally
      FQuery.close;
      FConnection.disconnect;

      FreeAndNil(FQuery);
      FreeAndNil(FConnection);

      sleep(250);
    end;
  end;  
end;

Вот событие, которое получает сообщение из потока.

procedure TfrmMain.message(msg : TMessage);
var
  TestPointerRecord : PTestPointerRecord;
begin
  TestPointerRecord := PTestPointerRecord(msg.lParam);
  try
    edit1.Text := inttostr(TestPointerRecord.i);  
  finally
    Dispose(TestPointerRecord);
  end;
end;

Приложение будет использоваться как приложение типа службы, которое будет работать непрерывно все время.

Вопросы:
1. Правильно ли я располагаю указатель?
2. Когда я проверил свой диспетчер задач во время работы приложения, я заметил, что на вкладке «Процессы» я заметил, что память (частный рабочий набор) постоянно увеличивается. Это нормально?

С уважением ко всем


person Francis Carillo    schedule 30.10.2018    source источник
comment
Вызов Dispose в порядке. Большая проблема заключается в том, что дескриптор окна может быть воссоздан. Катастрофа, если это воссоздание произойдет в потоке. Вам нужно использовать выделенный дескриптор окна, созданный вызовом AllocateHWnd.   -  person David Heffernan    schedule 30.10.2018
comment
Конечно, поскольку вы отправляете сообщение, поток блокируется до тех пор, пока сообщение не будет обработано. Так что нет необходимости распоряжаться в основном потоке. Вы можете распоряжаться в потоке. На самом деле вам даже не нужно динамическое распределение. Локальная переменная в порядке.   -  person David Heffernan    schedule 30.10.2018
comment
@DavidHeffernan привет, спасибо за ответ. Я видел этот ответ из связанного сообщения, stackoverflow.com/a/19063457/5056112. Я видел, как ты спорил с кем-то в этом посте. Мне было интересно, альтернативный ответ, который Реми разместил здесь, который, я думаю, то же самое, что вы пытаетесь сказать мне прямо сейчас, как вы думаете, можно использовать? Не приведет ли это к утечке памяти? Спасибо   -  person Francis Carillo    schedule 31.10.2018
comment
Там код использует PostMessage, который является асинхронным. Что касается вопросов, которые вы поднимаете в комментариях, читайте мои предыдущие комментарии выше.   -  person David Heffernan    schedule 31.10.2018
comment
@DavidHeffernan да, это PostMessage. Я пытаюсь рассказать вам о создании дескриптора окна. Мне было интересно, могу ли я использовать тот же способ, которым Реми создал дескриптор окна в сообщении?   -  person Francis Carillo    schedule 31.10.2018
comment
Да, ты можешь. РаспределитьHWnd. Согласно моему комментарию также.   -  person David Heffernan    schedule 31.10.2018


Ответы (1)


Я попробовал предложение Дэвида Хеффернана об использовании отдельного дескриптора, а не дескриптора основной формы. Это предложение на самом деле не решило проблему, НО благодаря Дэвиду, его стоит использовать, поскольку он уделил большое внимание проблемам, которые могут возникнуть, когда дескриптор основной формы использовался для получения сообщения, а окно было перерисовано или воссоздано.

Путем более глубокого изучения моих кодов, отладки, проб и ошибок. Я обнаружил, что проблема повторяется, когда я создаю соединение и запрашиваю базу данных. Обратите внимание: я использую ZeosLib для подключения к базе данных, и кажется, что каждый раз, когда мой поток зацикливается, выполняя операции с базой данных, рабочая частная память продолжает увеличиваться, и я не уверен, что Zeoslib вообще является потокобезопасным. Поэтому я переключился на ADO, и все прошло хорошо. Объем рабочей частной памяти остается стабильным.

Спасибо за помощь.

person Francis Carillo    schedule 05.11.2018