Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > Delphi > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Ответ
 
Опции темы
Старый 06.01.2018, 16:56   #1
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 383
Репутация: 16
По умолчанию Чтение файла в потоке. Не понятно что жрет память.

Доброе время суток.
Есть программа, которая генерирует лог в диапазоне от 1 до 10 секунд (каждые).
Моя программа читает лог каждые 10сек.
Чтоб не было ошибки:

«Cannot open file …. процесс не может получить доступ к файлу, так как этот файл занят другим процессом.»

Решил вынести чтение лога в отдельный поток.

Код:

TFileReadThread = class(TThread)
    private
    { Private declarations }
    PathFile: string;
  protected
    procedure Execute; override;
  public
    constructor Create(APathFile: String);      
  end;

var
  FileReadThread: TFileReadThread;


constructor TFileReadThread.Create(APathFile: String);
begin
  inherited Create(False);
  PathFile := APathFile;
end;

procedure TFileReadThread.Execute;
var
  LFile: TStringList;
  LIndex, LIndex1, LNumGPU, L_Length: integer;
  LValue, LStringParams: string;
  LValueTrue: boolean;
begin
  while not Terminated do
  begin
    try
      FMain.lValueStatus.Caption := 'File begin reading';
      FMain.lValueStatus.Font.Color := clGreen;
      LFile := TStringList.Create;
      LFile.LoadFromFile(PathFile);                              
      L_Length := LFile.Count-1;
      LStringParams := '';
      LValueTrue := false;
      LValue := '';
      LNumGPU := 0;


      for LIndex := L_Length downto 0 do
        if Pos('ETH: GPU0', LFile.Strings[LIndex]) <> 0 then
        begin
          FMain.edGPU0.Clear;
          FMain.edGPU1.Clear;
          LStringParams := LFile.Strings[LIndex];
          for LIndex1 := 0 to length(LStringParams) do
          begin
            if (LStringParams[LIndex1] in ['0'..'9']) then
              LValue := LValue+LStringParams[LIndex1]
            else
              if ((LStringParams[LIndex1] = '.')
                or (LStringParams[LIndex1] = ','))
                and (LValue <> '') then
              begin
                LValue := LValue+'.';
                LValueTrue := true;
              end
              else 
              begin
                if (LStringParams[LIndex1] = ' ')
                  and (LValueTrue) then
                begin
                  if (FMain.edGPU0.Text = '')
                    and (LNumGPU = 0) then
                    FMain.edGPU0.Text := LValue;
                  if (FMain.edGPU1.Text = '')
                    and (LNumGPU = 1)  then
                    FMain.edGPU1.Text := LValue;  
                  inc(LNumGPU);  
                end  
                else LValueTrue := false;
                LValue := '';  
              end;
          end;  
          break;
        end;

      LValue := '';
      LNumGPU := 0;
      for LIndex := L_Length downto 0 do
        if Pos('GPU0 t=', LFile.Strings[LIndex]) <> 0 then
        begin
          FMain.edTemp0.Clear;
          FMain.edTemp1.Clear;
          LStringParams := LFile.Strings[LIndex];
          for LIndex1 := 0 to length(LStringParams) do
          begin
            if (LStringParams[LIndex1] in ['0'..'9']) then
              LValue := LValue+LStringParams[LIndex1]
            else
              begin
                if (LStringParams[LIndex1] = 'C') then
                begin
                  if (FMain.edTemp0.Text = '')
                    and (LNumGPU = 0) then
                    FMain.edTemp0.Text := LValue;
                  if (FMain.edTemp1.Text = '')
                    and (LNumGPU = 1)  then
                    FMain.edTemp1.Text := LValue;  
                  inc(LNumGPU);  
                end  
                else LValueTrue := false;
                LValue := '';  
              end;
          end;  
          break;
        end;
         FMain.lValueStatus.Caption := 'File end reading';
         FreeAndNil(LFile);
          
         FileReadThread.Terminate;
         FileReadThread.WaitFor;
         FreeAndNil(FileReadThread);
         inherited Destroy;
    except
    on E: Exception do
      begin
        FMain.lValueStatus.Caption := 'Not access to file';
        FMain.lValueStatus.Font.Color := clRed;
        LFile.Free;
      end
    end;
  end;  
end;

Вызываю поток каждые 10сек. С помощью «Timer»
Код:

procedure TFMain.tPollDirectoryTimer(Sender: TObject);
var
  LNewFile: TSearchRec;
  LFileTime, LFileSize: integer;
  LPathFile, LFileName: string;
begin
  lValueStatus.Font.Color := clGreen;  
  LFileTime := 0;
  if FindFirst(edPathLog.Text+'*_log.txt', faAnyFile - faDirectory - faVolumeID, LNewFile) = 0 then
  repeat
    if LFileTime = 0 then
    begin
      LFileTime := LNewFile.Time;
      LFileSize := LNewFile.Size;
      LFileName := LNewFile.Name;
    end;
    
    if LFileTime < LNewFile.Time then
    begin
      LFileTime := LNewFile.Time;
      LFileSize := LNewFile.Size; 
      LFileName := LNewFile.Name; 
    end;  
  until FindNext(LNewFile) <> 0;
  FindClose(LNewFile);

  FileReadThread := TFileReadThread.Create(edPathLog.Text+LFileName);
  FileReadThread.Priority := tpNormal;

    
  laFileName.Caption := LFileName; 
  laFileTime.Caption := DateTimeToStr(FileDateToDateTime(LFileTime));
  laFileSize.Caption := IntToStr(LFileSize);

  if Pr_OldTime <> 0 then
  begin  
    if (Pr_OldTime = LFileTime) 
      and (Pr_OldSize = LFileSize) then
    begin
      EndPointVolume.SetMasterVolumeLevelScalar(1, nil);    
      SOURCE_BEEP(LOG);
      
      WRITE_LOG_FILE;
    end;
  end;
  Pr_OldName := LFileName;
  Pr_OldSize := LFileSize;
  Pr_OldTime := LFileTime;
end;

В результате я создаю только поток («FileReadThread») и «LFile», но я их все уничтожаю.

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

Спасибо за ответ.
KBO вне форума   Ответить с цитированием
Старый 06.01.2018, 17:06   #2
Аватар
Модератор
Заслуженный модератор
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Адрес: Северодонецк.ua
Сообщений: 18,086
Репутация: 6385
По умолчанию

Стринглист освобождаешь по исключению, а без исключения кто это делать будет?
Код:

FMain.edGPU0.Text := LValue;

Из-за того и подобного рано или поздно рухнет основной поток. Низзя к vcl из потока без синхронизации обращаться

Destroy из Execute это как?
__________________
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума   Ответить с цитированием
Старый 06.01.2018, 17:47   #3
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 383
Репутация: 16
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
Стринглист освобождаешь по исключению, а без исключения кто это делать будет?
Нет, стринглист, я освобождаю и в исключении
Код:

LFile.Free;

и в потоке
Код:

FreeAndNil(LFile);

хотя и разными методами (посмотрите внимательно)

Да синхронизацию я забыл - спасибо наплмнили
и с "Destroy" намутил... уберу его

Последний раз редактировалось KBO; 06.01.2018 в 17:52.
KBO вне форума   Ответить с цитированием
Старый 06.01.2018, 21:01   #4
evg_m
Профессионал
 
Регистрация: 20.04.2008
Сообщений: 4,761
Репутация: 2097
По умолчанию

Цитата:
Код:

         FileReadThread.Terminate;
         FileReadThread.WaitFor;
         FreeAndNil(FileReadThread);
         inherited Destroy;

это что попытка остановить и разрушить поток из самого потока?
для самостоятельной остановки достаточно просто дойти до конца процедуры(убрав первоначальный цикл)

или наиболее разумное предложение.
наоборот оставить цикл и убрать(Timer) кучу новых потоков.
а в цикле при необходимости добавить sleep()
и тогда имеем ОДИН нормальный бесконечный(постоянно работающий) поток и можем при необходимости остановить его извне
Код:

 FileReadThread.Terminate;

как только поток сможет проработать дольше чем до следующего запуска.
то остановлен и разрушен будет совсем другой поток, а старый уйдет в небытие с потерей (утечкой) ресурсов.
глобальная переменная в потоке почти тоже что и VCL в нем.
__________________
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума   Ответить с цитированием
Старый 06.01.2018, 22:17   #5
Alex11223
Модератор
Заслуженный модератор
 
Регистрация: 12.01.2011
Сообщений: 17,380
Репутация: 3353

icq: 512-765
skype: alexp.frl
По умолчанию

А я один не понял каким образом поток решает проблему с ошибкой доступа к файлу?
Alex11223 вне форума   Ответить с цитированием
Старый 06.01.2018, 23:09   #6
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 383
Репутация: 16
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
А я один не понял каким образом поток решает проблему с ошибкой доступа к файлу?
Я не то имел ввиду - неправильно выразился, там не в потоке дело, просто не пользовался конструкцией "try... except"
KBO вне форума   Ответить с цитированием
Старый 06.01.2018, 23:11   #7
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 383
Репутация: 16
По умолчанию

Цитата:
Сообщение от evg_m Посмотреть сообщение
это что попытка остановить и разрушить поток из самого потока?
bиз 4-х строк, оставил просто "Terminate".
Код:

procedure TFileReadThread.Execute;
var
  LFile: TStringList;
  LIndex, LIndex1, LNumGPU, L_Length: integer;
  LValue, LStringParams: string;
  LValueTrue: boolean;
begin
  while not Terminated do
  begin
    try
      Pr_Status := 'File begin reading';
      Pr_Status_Color := clGreen;
      Synchronize(UpdStatus);

      LFile := TStringList.Create;
      LFile.LoadFromFile(PathFile);                              
      L_Length := LFile.Count-1;
      LStringParams := '';
      LValueTrue := false;
      LValue := '';
      LNumGPU := 0;

      for LIndex := L_Length downto 0 do
        if Pos('ETH: GPU0', LFile.Strings[LIndex]) <> 0 then
        begin
          LStringParams := LFile.Strings[LIndex];
          for LIndex1 := 0 to length(LStringParams) do
          begin
            if (LStringParams[LIndex1] in ['0'..'9']) then
              LValue := LValue+LStringParams[LIndex1]
            else
              if ((LStringParams[LIndex1] = '.')
                or (LStringParams[LIndex1] = ','))
                and (LValue <> '') then
              begin
                LValue := LValue+'.';
                LValueTrue := true;
              end
              else 
              begin
                if (LStringParams[LIndex1] = ' ')
                  and (LValueTrue) then
                begin
                  if (FMain.edGPU0.Text = '')
                    and (LNumGPU = 0) then
                    begin
                      Pr_ValGPU := LValue;
                      Synchronize(UpdGPU0);   
                    end;
                  if (FMain.edGPU1.Text = '')
                    and (LNumGPU = 1) then
                    begin
                      Pr_ValGPU := LValue;
                      Synchronize(UpdGPU1);   
                    end;
                  inc(LNumGPU);  
                end  
                else LValueTrue := false;
                LValue := '';  
              end;
          end;  
          break;
        end;

      LValue := '';
      LNumGPU := 0;
      for LIndex := L_Length downto 0 do
        if Pos('GPU0 t=', LFile.Strings[LIndex]) <> 0 then
        begin
          LStringParams := LFile.Strings[LIndex];
          for LIndex1 := 0 to length(LStringParams) do
          begin
            if (LStringParams[LIndex1] in ['0'..'9']) then
              LValue := LValue+LStringParams[LIndex1]
            else
              begin
                if (LStringParams[LIndex1] = 'C') then
                begin
                  if (FMain.edTemp0.Text = '')
                    and (LNumGPU = 0) then
                    begin
                      Pr_ValTemp := LValue;
                      Synchronize(UpdTemp0);   
                    end;
                  if (FMain.edTemp1.Text = '')
                    and (LNumGPU = 1)  then
                    begin
                      Pr_ValTemp := LValue;
                      Synchronize(UpdTemp1);   
                    end;
                  inc(LNumGPU);  
                end  
                else LValueTrue := false;
                LValue := '';  
              end;
          end;  
          break;
        end;
        Pr_Status := 'File end reading';
        Pr_Status_Color := clGreen;
        Synchronize(UpdStatus);
        FreeAndNil(LFile);
        FileReadThread.Terminate;
    except
    on E: Exception do
      begin
        Pr_Status := 'Not access to file';
        Pr_Status_Color := clRed;
        Synchronize(UpdStatus);
        FreeAndNil(LFile);
      end
    end;
  end;  
end;

Хотя память занимаемая программой всеравно продолжает РОСТИ, медленно но растет.

А "Timer", использова просто для того чтоб через каждые 10сек,

Последний раз редактировалось KBO; 06.01.2018 в 23:29.
KBO вне форума   Ответить с цитированием
Старый 06.01.2018, 23:22   #8
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 383
Репутация: 16
По умолчанию

Цитата:
Сообщение от evg_m Посмотреть сообщение
а в цикле при необходимости добавить sleep()
т.е. если я вас правильно понял, вы предлагаете присто при создании формы создать поток и его зациклить с "sleep(10000)" например 10сек?
и если что потом я могу с главного потока изменять значение "sleep"
KBO вне форума   Ответить с цитированием
Старый 07.01.2018, 10:56   #9
evg_m
Профессионал
 
Регистрация: 20.04.2008
Сообщений: 4,761
Репутация: 2097
По умолчанию

Цитата:
если что потом я могу с главного потока изменять значение "sleep"
почему бы и нет, только надо помнить(знать,понимать) что изменение задержки проявиться не сразу, а только со следующей итерации цикла.

Код:

        FileReadThread.Terminate;

это остановка не самого себя, а последнего запущенного(того который был ПОСЛЕДНИМ записан в данную переменную)
Код:

  FileReadThread := TFileReadThread.Create(edPathLog.Text+LFileName);

Код:

self.Terminate;

но это всего лишь
Код:

self.terminated:=true;

__________________
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 07.01.2018 в 11:26.
evg_m вне форума   Ответить с цитированием
Старый 07.01.2018, 22:14   #10
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 383
Репутация: 16
По умолчанию

и всеже я хочу понять что сжирает память.
БЕЗ следующих строк (использующихся в потоке), память НЕ теряется
Код:

      for LIndex := L_Length downto 0 do
        if Pos('ETH: GPU0', LFile.Strings[LIndex]) <> 0 then
        begin
          LStringParams := LFile.Strings[LIndex];
          for LIndex1 := 0 to length(LStringParams) do
          begin
            if (LStringParams[LIndex1] in ['0'..'9']) then
              LValue := LValue+LStringParams[LIndex1]
            else
              if ((LStringParams[LIndex1] = '.')
                or (LStringParams[LIndex1] = ','))
                and (LValue <> '') then
              begin
                LValue := LValue+'.';
                LValueTrue := true;
              end
              else 
              begin
                if (LStringParams[LIndex1] = ' ')
                  and (LValueTrue) then
                begin
                  if (FMain.edGPU0.Text = '')
                    and (LNumGPU = 0) then
                    begin
                      Pr_ValGPU := LValue;
                      Synchronize(UpdGPU0);   
                    end;
                  if (FMain.edGPU1.Text = '')
                    and (LNumGPU = 1) then
                    begin
                      Pr_ValGPU := LValue;
                      Synchronize(UpdGPU1);   
                    end;
                  inc(LNumGPU);  
                end  
                else LValueTrue := false;
                LValue := '';  
              end;
          end;  
          break;
        end;

      LValue := '';
      LNumGPU := 0;
      for LIndex := L_Length downto 0 do
        if Pos('GPU0 t=', LFile.Strings[LIndex]) <> 0 then
        begin
          LStringParams := LFile.Strings[LIndex];
          for LIndex1 := 0 to length(LStringParams) do
          begin
            if (LStringParams[LIndex1] in ['0'..'9']) then
              LValue := LValue+LStringParams[LIndex1]
            else
              begin
                if (LStringParams[LIndex1] = 'C') then
                begin
                  if (FMain.edTemp0.Text = '')
                    and (LNumGPU = 0) then
                    begin
                      Pr_ValTemp := LValue;
                      Synchronize(UpdTemp0);   
                    end;
                  if (FMain.edTemp1.Text = '')
                    and (LNumGPU = 1)  then
                    begin
                      Pr_ValTemp := LValue;
                      Synchronize(UpdTemp1);   
                    end;
                  inc(LNumGPU);  
                end  
                else LValueTrue := false;
                LValue := '';  
              end;
          end;  
          break;
        end;

но тут ничего такого нет, чтоб захламлять и не отдавать память

Последний раз редактировалось KBO; 07.01.2018 в 22:23.
KBO вне форума   Ответить с цитированием
Ответ

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Пустое приложение жрет память AlexAES C++ Builder 0 23.10.2017 23:29
Что быстрее, запись и чтение реестра или файла? lollollollol Общие вопросы Delphi 13 21.11.2015 10:47
Цикл грузит процессор и жрет память. DIgorevich Общие вопросы Delphi 3 29.07.2015 11:44
WEB-приложение жрет память alexey_kip Java для Web (EE, Servlet, JSP, Tomcat, Spring MVC) 4 29.05.2015 17:55
Что за процесс такой. Жрет 95-97-100% ресурсов CPU kzld Windows 7 11.02.2014 05:33


03:39.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru