Перейти к содержанию
Fire Monkey от А до Я
  • 0

Утечка памяти


antigrav

Вопрос

Здравствуйте, коллеги.

Пишу метод десериализации для считывания данных из файла и создания соответствующего объекта в памяти. Для того, чтобы пользователь не скучал, загружаю данные в отдельном потоке, а в главном запускаю TAniIndicator. Данные считываются, объект создается, AniIndicator работает. Но при попытке завершения приложения получаю утечку памяти (см. рис.). Пользовательские объекты я удаляю перед закрытием приложения, но в памяти остаются системные объекты, в том числе из библиотеки PPL. Сокращенный код метода загрузки данных ниже. С чем может быть связана утечка? Для детектирования утечек использую команду ReportMemoryLeaksOnShutdown := True. Если дополнительный поток не использую, утечек нет.

image.png.8b00fea0b153f4b4fca7da6dc12a6945.png

procedure LoadProjectFromFile(AFileName: string);
var
  fut: IFuture<TComponent>;
  cmp: TComponent;
begin
  AniIndic.Enabled := True;
  AniIndic.Visible := True;
  fut := TTask.Future<TComponent>(
    function: TComponent
    begin
      Result := LoadFromFile(AFileName);
    end
  );
  TTask.Run(
    procedure
    begin
      fut.Start;
      cmp := fut.Value;
      {$REGION 'После загрузки в главном потоке'}
      TThread.Synchronize(nil,
        procedure
        begin
          AniIndic.Enabled := False;
          AniIndic.Visible := False;
          if Assigned(cmp) then
          begin
            if cmp is TCAMProject then
            begin
              fProject := cmp as TCAMProject;
              // здесь всякие действия
              if Assigned(OnFinishedLoadProject) then
              begin
                OnFinishedLoadProject(nil);
              end;
            end
          end
        end
      )
      {$ENDREGION}
    end
  );
end;

Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Надо дождаться завершения тасков
например так:

procedure TmainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  //wait all tasks finished
  var ThreadPoolStats:=TThreadPoolStats.Default;
  if ThreadPoolStats.IdleWorkerThreadCount<>ThreadPoolStats.WorkerThreadCount then
  begin
    Action:=TCloseAction.caNone;
    TThread.ForceQueue(nil,
    procedure
    begin
      Application.MainForm.Close;
    end,300);
  end;
end;

 

Изменено пользователем Slym
Ссылка на комментарий
  • 0

Уважаемый Slym, к сожалению предложенный способ результата не дал. Если я правильно понял, условие  

ThreadPoolStats.IdleWorkerThreadCount<>ThreadPoolStats.WorkerThreadCount

является признаком того, что не все таски завершены. При тестировании приложения это условие не выполняется (то есть все такси завершены?), управление передается деструктору главной формы приложения, в котором дается команда на удаление пользовательских объектов. Пользовательские объекты удаляются. Затем выдается сообщение об утечке памяти и приложение закрывается.

Ссылка на комментарий
  • 0

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

ThreadPoolStats.IdleWorkerThreadCount=3

и 

ThreadPoolStats.WorkerThreadCount=3

Условие не выполняется, программа закрывается с утечкой.

Насколько я понял, ThreadPoolStats.IdleWorkerThreadCount хранит кол-во потоков, ожидающих завершения. 

Если, например, изменить условие на 

if ThreadPoolStats.IdleWorkerThreadCount>0

то приложение просто невозможно закрыть.

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...