Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Проблема с освобождением памяти в потоке [D7, XP]


KyRo ©   (2006-08-28 13:24:00) 

Добрый день  у меня проблема
Я создаю несколько нитей одну за другой и каждая из них парсит файл после чего забивает его в базу.
Во время парсинга для добовления в базу я динамически создою
в главной процедуре каждой нити компоненты АДО

IncTr:=TAdoQuery.Create(nil);
   With IncTr do
     begin
       Connection:= DBCONNECT;
       SQL.Clear;
       SQL.Add('Select * from INCLUDE_TR_TEHPRO where 1=1');
       open;
     end;

После того как процедура выполнилась и файл записан в базу я
освобождаю их
IncTr.Free;
И после этого когда другая нить еще не закончила работу и обращается к своему компоненту появляется ошибка доступа к памяти.
Из за чего такое может быть и как освободить память ведь каждая нить создает себе свой набор компонентов для работы с базой и ошибки по идее не должно быть !
И что будет если не освобождать вообще (Тогда ошибки нету)  ?


Ketmar   (2006-08-28 14:53:00) [1]

> [14] KyRo   (28.08.06 14:49)
> где она обращается к этим компонентам которые я освободил.
ась???


KyRo   (2006-08-28 14:49:00) [2]


> > появляется ошибка доступа к памяти
>
>
> И на какой конкретно строчке возникает это исключение ?


На любой строке другой нити где она обращается к этим компонентам которые я освободил .
То есть получается что эти компоненты не создаются в каждой нити свои , а создоются один раз и используются всеми нитями я так понимаю.


StriderMan   (2006-08-28 14:47:00) [3]


>    {  Registr.Free;
>       BlockList.Free;
>       TrList.Free;
>       FindTr.Free;
>       IncTr.Free;
>       TrInfo.Free;
>       DBCONNECT.Free; }

ужос!

чуть где Exception в теле процедуры - и останется куча висячих объектов!

d

try
finally
end

срочно!!


Ketmar   (2006-08-28 14:30:00) [4]

> [9] KyRo   (28.08.06 14:04)
ну не надо так, а? я старый, больной эльф... если моя психика не выдержит -- ты же не будешь меня содержать до смерти...


Fay   (2006-08-28 14:13:00) [5]

IOCP "сделай сам" 8)


Сергей М.   (2006-08-28 14:09:00) [6]


> KyRo   (28.08.06 14:04) [9]



> появляется ошибка доступа к памяти


И на какой конкретно строчке возникает это исключение ?


> пишу состояние потока , а из главной формы таймер переодически
> проверяет состояние потоков и если поток завершил работу
> он берет и запускает его снова на обработку другого файла


Дурней схемы не придумать)


KyRo   (2006-08-28 14:04:00) [7]


> Сергей М. ©   (28.08.06 13:55) [6]
> Какой процедуры ? Parsing_Tehpro ?

Да


> Ketmar ©   (28.08.06 13:55) [7]
> ой вэй. использование реестра для передачи параметров --
>  это инновация...

Я не передаю через реестр параметры между потоками.
В реестр я пишу состояние потока , а из главной формы таймер переодически проверяет состояние потоков и если поток завершил работу он берет и запускает его снова на обработку другого файла.
Сделано это потому что файлов может быть неограниченое количество , а потоков всего 5 ть


Сергей М.   (2006-08-28 13:55:00) [8]

Какой процедуры ? Parsing_Tehpro ?


Ketmar   (2006-08-28 13:55:00) [9]

ой вэй. использование реестра для передачи параметров -- это инновация...


Ketmar   (2006-08-28 13:55:00) [10]

для передачи параметров между потоками, натурально. %-)


KyRo   (2006-08-28 13:52:00) [11]

Это локальная переменная процедуры .


Сергей М.   (2006-08-28 13:48:00) [12]


> KyRo   (28.08.06 13:37) [3]


Ответь на [2]..


KyRo   (2006-08-28 13:37:00) [13]


> where 1=1

Это для того что бы когда компонент переводиш в опен он не тянул данные из базы она очень большая.

Весь екзекут очень большой заманаетесь читать
вот его кусок

Reg:=Tregistry.Create;
         Reg.RootKey:=HKEY_CURRENT_USER;
         Reg.OpenKey('\SOFTWARE\LogBn\StatusHread\'+ExtractFileName(FileN[NomHr])+'\', false);
         Reg.WriteString('ProcesID',IntToStr(NomHr));
         Reg.WriteString('ProcesStatus','Begin Pars');
         Reg.WriteString('StatusOp','Run');
         Parsing_Tehpro(FileN[NomHr],NomHr,include);
         Reg.WriteString('ProcesStatus','Pars Compl');
         Reg.WriteString('StatusOp','Compl');
         Reg.Free;


Где я пишу в реестр состояние нити и запускаю процедуру для парсинга этого файла и добовление в базу

Parsing_Tehpro(FileN[NomHr],NomHr,include);

Процедура тоже большая по этому вот ее основное тело


begin
  // Создаем компонент соединения с бд
     DBCONNECT:=TADOConnection.Create(nil);  {}
   With DBCONNECT do
    begin
     ConnectionReg:=TRegistry.Create;
     ConnectionReg.RootKey:=HKEY_CURRENT_USER;
     ConnectionReg.OpenKey('\SOFTWARE\LogBn\Settings\', false);
     ConnectionString:=ConnectionReg.ReadString('ConnectionString');
     DBCONNECT.LoginPrompt:=False;
     Connected := True;
     ConnectionReg.Free;
    end;
     // Создаем компоненты для работы с бд
   TrInfo:=TAdoQuery.Create(nil);
   With TrInfo do
     begin
       Connection:= DBCONNECT;
       SQL.Clear;
       SQL.Add('Select * from TR_INFO_TEHPRO where 1=1');
       open;
     end;
   IncTr:=TAdoQuery.Create(nil);
   With IncTr do
     begin
       Connection:= DBCONNECT;
       SQL.Clear;
       SQL.Add('Select * from INCLUDE_TR_TEHPRO where 1=1');
       open;
     end;
   FindTr:=TAdoQuery.Create(nil);
   With FindTr do
     begin
       Connection:= DBCONNECT;
     end;
    //Обнуляем айди имени банкомата
    ATM_Name_Id:=0;
    //Узнаем дату транзакций из имени файла
    Date_TR:=Date_From_FileName(FileN);
    //Узнаем айди атм
    ATMNAME_From_File(FileN);
   //Создаем список и загружаем в него файл с транзакциями
     TrList:=TstringList.Create;
     TrList.LoadFromFile(FileN);
   //Создаем список для разбиения основного на блоки транзакций
     BlockList:=TstringList.Create;
     metka:=0;
      //Создаем компонент для изменений статуса
      Registr:=Tregistry.Create;
      Registr.RootKey:=HKEY_CURRENT_USER;
      Registr.OpenKey('\SOFTWARE\LogBn\StatusHread\'+ExtractFileName(FileN)+'\', false);
    // Начинаем парсить главный список
    For i := 0 to TrList.Count -1 do
      BEGIN
   //Отлавливаем начало блока транзакций
       if (ParsStFunc.TailPos(TrList.Strings[i],'->',1)>0)
         then
           begin
            metka:=1;
            BlockList.Add(TrList.Strings[i]);
           end;
      //Отлавливаем входящие транзакции
      if ((ParsStFunc.TailPos(TrList.Strings[i],'->',1)=0)and
         (ParsStFunc.TailPos(TrList.Strings[i],'<-',1)=0))
         then
           //Проверяем было ли начала блока транзакций или это неучтенная
           if (metka <> 0)and(i<>TrList.Count -1)
              then
                 BlockList.Add(TrList.Strings[i])
              else
                 begin
                  BlockList.Add(TrList.Strings[i]);
                  DbADD(BlockList);
                  BlockList.Clear;
                 end;
      //Отлавливаем конец блока транзакций
      if (ParsStFunc.TailPos(TrList.Strings[i],'<-',1)>0)
         then
           begin
             BlockList.Add(TrList.Strings[i]);
             DbADD(BlockList);
             BlockList.Clear;
             metka:=0;
           end;
      END;
    {  Registr.Free;
      BlockList.Free;
      TrList.Free;
      FindTr.Free;
      IncTr.Free;
      TrInfo.Free;
      DBCONNECT.Free; }
 end;


И вот в конце я освобождаю память.
То есть если подробно то из каждой нити я запускаю эту процедуру которая находится в отдельном модуле.


StriderMan   (2006-08-28 13:30:00) [14]


> where 1=1

а это зачем?

выложи весь Execute твоего класса Thread.


Сергей М.   (2006-08-28 13:30:00) [15]


> IncTr


Это что ? Лок.переменная ? Поле поточного класса ?


Наверх

Титульная страница Поиск, карта сайта Написать письмо