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

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

Подскажите почему я не могу освободить поток [D7, XP, 2003]


Страницы:   1 2

KyRo ©   (2006-12-01 11:30:00) 

Я создаю поток
 StatusATMT:=TStatusATMThread.Create(False);


constructor TStatusATMThread.Create(CreateSuspennded: Boolean);
  begin
     inherited Create(CreateSuspennded) ;
      // Создаем сервер
    ServerS:=TServerSocket.Create(nil);
    ServerS.OnClientError:=ServerClientError;
    ServerS.OnClientRead:=ServerClientRead;
    ClientS:=TClientSocket.Create(nil);
    ClientS.OnError:=ClientError;
    ClientS.OnConnect:=ClientConnect;
    ClientS.ClientType:=ctNonBlocking;
    //priority:=tpLowest;
    Resume;
  end;


В EXECUTE есть соответственно цикл который запускает сокет сервер и клиент и начинает работать по сети с клиентами

While not Terminated do
  begin
       ATML:=TStringList.Create;
   {Запрашиваем список ай пи адресов клиентов которых надо опросить}
   if  LoadATMList(ATML) =False
      then
         begin
          ATML.Free;
          Terminate;
         end;
   {Запускаем опрос}
   For i := 0 to ATML.Count -1 do
       begin
         {Запускаем сервер}
          ServerS.ServerType:=stNonBlocking;
          ServerS.Port:=50018;
          ServerS.Active:=True;
          и.т.д

При выходе из этого цикла (то есть в конце экзекют) я освобождаю сервер и клиент


ServerS.Free;
   ClientS.Free;
   ATML.Free;


И вот из основной программы я пытаюсь его освободить и на этом программа залипает !!!

StatusATMT.Terminate;
StatusATMT.Free;


StatusATMT -это глобальная переменная С типом TStatusATMThread

Подскажите из за чего это может происходить ?


clickmaker   (2006-12-01 12:27:00) [21]


> А таймер мне нужен что бы сделать тайм аут на то сколько
> сервер будет ожидать ответа от клиента

а почему бы Sleep не сделать? или через события? TEvent, WaitFor


Сергей М.   (2006-12-01 12:27:00) [22]


> Что это такое можно по подробнее ?
>


Подробности - в справке и msdn.

А вкратце - эти ф-ции инициализируют/деинициализируют COM-подсистему для работы в текущем код.потоке. АДО как раз и базируется на OLE/COM.


KyRo   (2006-12-01 12:22:00) [23]


> CoInitialize(nil);
> try
> .. работа с АДО, от начала и до конца ...
> finally
>  CoUninitialize;
> end;

Что это такое можно по подробнее ?


> это у него не сработает, т.к. до этого просто не дойдет,
>  до него куча кода который уже "залипает", тут для этого
> при такой структуре нужен отдельный поток обрабатывающий
> рабочий, и вот в нем уже можно делать так. (но лучше конечно
> делать правильно ;)


тут вы не правы все отлично работает . Не могу только завершить поток.
А таймер мне нужен что бы сделать тайм аут на то сколько сервер будет ожидать ответа от клиента. И когда переходить на обработку следующего


sniknik   (2006-12-01 12:16:00) [24]

> Имеете ввиду вот этот цикл ? Поставить после него проверку на Terminated
> и если есть то Exit ? Я правильно понял ?
нет. я имел ввиду первый показанный цикл, и не после него а в нем. разница однако!

>  {Запускаем опрос}
>    For i := 0 to ATML.Count -1 do
>        begin
>          {Запускаем сервер}
>           ServerS.ServerType:=stNonBlocking;
>           ServerS.Port:=50018;
>           ServerS.Active:=True;
>           и.т.д


но после показан код который разбирать совсем не хочется, его проще переделать.


Сергей М.   (2006-12-01 12:16:00) [25]


> sniknik ©   (01.12.06 12:13) [15]


> это у него не сработает, т.к. до этого просто не дойдет,
>  до него куча кода который уже "залипает"


Это понятно.

Но, согласись, грамотная организация такого цикла (если он необходим, а он при данной логике действительно необходим) - один из ключевых моментов в сквозной логике.


sniknik   (2006-12-01 12:13:00) [26]

Сергей М. ©   (01.12.06 12:07) [12]
> while not Terminated and GetMessage(Msg, 0, 0, 0) do
> DispatchMessage(Msg);
это у него не сработает, т.к. до этого просто не дойдет, до него куча кода который уже "залипает", тут для этого при такой структуре нужен отдельный поток обрабатывающий рабочий, и вот в нем уже можно делать так. (но лучше конечно делать правильно ;)


Сергей М.   (2006-12-01 12:11:00) [27]

Ну и еще один крайне важный момент:

CoInitialize(nil);
try
.. работа с АДО, от начала и до конца ...
finally
  CoUninitialize;
end;

Выделенное жирным обязательнодля исполнения в каждом доп.потоке, в котором осуществляется работа с АДО (и не только с ним)

В противном случае будет возбуждено исключение и твой поток "залипнет", поскольку в нем нет общей обработки исключений.


sniknik   (2006-12-01 12:09:00) [28]

> Я не обращаюсь в всл Application.ProcessMessages ; для того что бы работали события таймера ,клиента и сервера которые
> функционируют в этом потоке
да? покажи выборку сообщений своего потока, и зачем одноименно назвал (Application) обрабатывающий поток с основным?...

сдается мне мил человек, что ты ... эта, в кучу все смешал, и пользуешься без разбора в потоке глобальными таймерами/переменными, из потока их только стартуешь.


Сергей М.   (2006-12-01 12:07:00) [29]


> Я не обращаюсь в всл Application.ProcessMessages


Здрасть-приехали !

Application - это что по-твоему ? Не VCL-объект, надо понимать ?


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


Насчет таймера в код не вникал, но более чем уверен - он там нафиг не нужен.

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

while not Terminated and GetMessage(Msg, 0, 0, 0) do
 DispatchMessage(Msg);

И все ! И никаких Application.ProcessMessages тут не нужно ! Все при этом расчудесно работает)


clickmaker   (2006-12-01 11:58:00) [30]


> Залипает на строке которй я его пытаюсь освободить

procedure TThread.Terminate;
begin
 FTerminated := True;
end;

здесь залипать нечему, как видишь

destructor TThread.Destroy;
begin
 if (FThreadID <> 0) and not FFinished then
 begin
   Terminate;
   if FCreateSuspended then
     Resume;
   WaitFor;
 end;

а вот здесь может залипнуть на WaitFor. Значит, где-то внутри Execute


KyRo   (2006-12-01 11:54:00) [31]


> В коде куча грубых ошибок.
> Проще все переписать с нуля, чем их исправлять.

Это легче всего сказать !!


> Насколько мне помнится, ты уже получал граблями за обращение
> к VCL-компонентам в доп.потоке, и теперь вновь на них наступаешь.
>


> > Application.ProcessMessages ;
> в потоке ????? убери пока больше никто не видел...


Я не обращаюсь в всл Application.ProcessMessages ; для того что бы работали события таймера ,клиента и сервера которые функционируют в этом потоке


KyRo   (2006-12-01 11:52:00) [32]


> try
> //все остальное сдесь
> //например
> if  LoadATMList(ATML) = False then Break; //или Exit если
> вдруг вложенных циклов станет больше одного, и нужно выйти
> а Break этого уже позволит.
>
> ....
>
> finally
>  ATML.Free;
> end;


Так да можно сделать.
> [1] +
> > из за чего это может происходить ?
> в цикле, который выполняется долго, нет проверки на Terminated
> и выхода если установлен, вот он его до конца и прокручивает.
>



> //Ожидаем ответа или выхода таймаута
>         While (StatusWake = 0)and(not Terminated) do Application.
> ProcessMessages ;


Имеете ввиду вот этот цикл ? Поставить после него проверку на Terminated
и если есть то Exit ? Я правильно понял ?


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


Залипает на строке которй я его пытаюсь освободить


sniknik   (2006-12-01 11:48:00) [33]

> Application.ProcessMessages ;
в потоке ????? убери пока больше никто не видел...


Сергей М.   (2006-12-01 11:48:00) [34]


> KyRo


В коде куча грубыхошибок.
Проще все переписать с нуля, чем их исправлять.

p.s.
Насколько мне помнится, ты уже получал граблями за обращение к VCL-компонентам в доп.потоке, и теперь вновь на них наступаешь.


sniknik   (2006-12-01 11:46:00) [35]

[1] +
> из за чего это может происходить ?
в цикле, который выполняется долго, нет проверки на Terminated и выхода если установлен, вот он его до конца и прокручивает.

++
ATML:=TStringList.Create;
try
//все остальное сдесь
//например
if  LoadATMList(ATML) = False then Break; //или Exit если вдруг вложенных циклов станет больше одного, и нужно выйти а Break этого уже позволит.

....

finally
 ATML.Free;
end;


clickmaker   (2006-12-01 11:45:00) [36]

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


KyRo   (2006-12-01 11:42:00) [37]


> Причина в "и. т. д."

:)

Держите расшифровку (весь execute)


var
ATML:TStringList;
i:Integer;
ipclientIMG:String;
//**************************************************
{Функция определяет количество банкоматов с прописаным ай пи адресом}
Function LoadATMList(var ATML:TStringList):Boolean;
var
  DBCONNECT:TADOConnection;
  ADOQUERY:TADOQuery;
  ConnectionReg:Tregistry;
  ConString:String;
  i:Integer;
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;
   end;
     ConnectionReg.Free;
  //Создаем кмпонент АДО ТЕЙБЛ
    ADOQUERY:=TADOQuery.Create(nil);
  // Задаем параметры соединения
  With ADOQUERY do
   begin
     Connection:= DBCONNECT;
     ADOQUERY.SQL.Add('Select * from ATM_NAME where IP_CLIENT IS NOT NULL order by NAME');
     Active:=True;
   end;
   if ADOQUERY.RecordCount = 0
      then
        begin
          ADOQUERY.Free;
          DBCONNECT.Connected:=False;
          DBCONNECT.Free;
          Result:=False;
          Exit;
        end;
   ADOQUERY.First;
  For i:= 1 to ADOQUERY.RecordCount do
    begin
      ATML.Add(ADOQUERY.FieldValues['IP_CLIENT']);
      ADOQUERY.Next;
    end;
  if ATML.Count > 0
     then
       begin
         Result:=True;
         ADOQUERY.Free;
         DBCONNECT.Connected:=False;
         DBCONNECT.Free;
       end
     else
       begin
          ADOQUERY.Free;
          DBCONNECT.Connected:=False;
          DBCONNECT.Free;
          Result:=False;
       end;
end;
//**************************************************
{Функция модификации записи статуса клиента в базе данных}
Procedure ModifyBD(IPADDR:String);
  var
  DBCONNECT:TADOConnection;
  ADOQUERY:TADOQuery;
  ConnectionReg:Tregistry;
  ConString:String;
 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;
   end;
     ConnectionReg.Free;
  //Создаем кмпонент АДО ТЕЙБЛ
    ADOQUERY:=TADOQuery.Create(nil);
  // Задаем параметры соединения
  With ADOQUERY do
   begin
     Connection:= DBCONNECT;
     ADOQUERY.SQL.Add('Select * from ATM_NAME where IP_CLIENT='+#39+IPADDR+#39);
     Active:=True;
   end;
   if ADOQUERY.RecordCount = 0
      then
        begin
          ADOQUERY.Free;
          DBCONNECT.Free;
          Exit;
        end;
  If ResMassag<>''
  then
    begin
     ADOQUERY.Edit;
     ADOQUERY.FieldByName('STATUS_CLIENT').Value:='Работает';
     ADOQUERY.Post;
    end
  else
    begin
     ADOQUERY.Edit;
     ADOQUERY.FieldByName('STATUS_CLIENT').Value:='Не доступен';
     ADOQUERY.Post;
    end;
 ADOQUERY.Active:=False;
 DBCONNECT.Connected:=False;
 ADOQUERY.Free;
 DBCONNECT.Free;
 end;
//**************************************************
begin
While not Terminated do
  begin
       ATML:=TStringList.Create;
   {Запрашиваем список ай пи адресов клиентов которых надо опросить}
   if  LoadATMList(ATML) =False
      then
         begin
          ATML.Free;
          Terminate;
         end;
   {Запускаем опрос}
   For i := 0 to ATML.Count -1 do
       begin
         {Запускаем сервер}
          ServerS.ServerType:=stNonBlocking;
          ServerS.Port:=50018;
          ServerS.Active:=True;
         // Cоздаем клиент
         ClientS.Active:=False;
         ipclientIMG:=ATML.Strings[i];
         DelSpacesUn(ipclientIMG);
         Messag:=ipclientIMG;
         ClientS.Address:=ipclientIMG;
         ClientS.Port:=50017;
         ClientS.Tag:=0;
         ResMassag:='';
         StatusWake:=0;
          Application.ProcessMessages ;
        try
          ClientS.Active:=True;
          Application.ProcessMessages ;
        Except
         Continue;
        end;
        {---! Запускаем таймер который будет следить за работай сервера }
        TimerServerWork:=TTimer.Create(nil);
        TimerServerWork.OnTimer:=TimerServerWorkOnTimer;
        TimerServerWork.Interval:=10000;
        TimerServerWork.Enabled:=True;
        //Ожидаем ответа или выхода таймаута
        While (StatusWake = 0)and(not Terminated) do Application.ProcessMessages ;
        //Тушим сервер и таймер
        TimerServerWork.Enabled:=False;
        TimerServerWork.Free;
        ServerS.Active:=False;
        //Модифицируем базу данных
        ModifyBD(Messag);
      end;
  ATML.Free;
  end;
  ServerS.Active:=False;
  ClientS.Active:=False;
  try
   ServerS.Free;
   ClientS.Free;
   ATML.Free;
  except
   Break;
  end;


KyRo   (2006-12-01 11:40:00) [38]


> а почему не просто Break?


Можно и Break? не спорю но тогда надо освободить сервер и клиент или они вместе с потоком освободятся автоматом когда я его уничтожу?


> И зачем свойства в цикле каждый раз по новой назначать?


Свойства чего сервера ? Если да то для разных клиентов разные параметры.


С   (2006-12-01 11:39:00) [39]

Причина в "и. т. д."


clickmaker   (2006-12-01 11:34:00) [40]


> if  LoadATMList(ATML) =False
>       then
>          begin
>           ATML.Free;
>           Terminate;
>          end;

а почему не просто Break? И зачем свойства в цикле каждый раз по новой назначать?


Страницы:   1 2

Наверх

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