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

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

Как правильно удалить поток в различных ситуациях


Страницы:   1 2 3

Kolan ©   (2006-05-30 19:04:00) 

Здравствуйте,
 Меня мучает вопрос как коректно удалить поток. Под словом удалить подразумеваю вызвать деструктор.

Кое кокие знания у меня есть, но что я делаю не так понять не могу.

1. Вопрос номер один:
   Каким образом удаляют поток?
   - Мой ответ: Нужно вызвать метод Terminate. И незабыть выставить FreeOnTeminateв True
Так?

   - Я знаю, что Terminateпросто устанавливает Terminatedв True, поэтому его нужно самому проверять.

Если 1 верно(если нет, то где я не прав), то вопрос номер 2:
Как быть в следующих случаях:
а). FreeOnTerminateзаписано внутри Execute. Поток зоздался спящим, так и небыл "разбужен", и его надо удалить. Те до FreeOnTerminateдело даже не дошло...

б). Поток чего-то ждет. Например ф-цией WaitForSingleObject. И его надо удалить.

в). В потоке используется экземпляр ранее написанного класса. И в этом классе совершаются долгие вычисления. Сатарый класс трогать на хочется. Тогда как быть и как проверять Terminated.

Во всех этих случиях у меня не вызывается деструктор потока...


Пусик   (2006-06-01 14:24:00) [21]


> Kolan ©   (01.06.06 14:22) [36]


> Как сделать чтобы дошло?


Ожидать завершения потока - метод WaitFor;


Kolan   (2006-06-01 14:23:00) [22]


> И что? Чему это может помешать?

В этом случае произайдет закрытие метедоа...


Пусик   (2006-06-01 14:22:00) [23]


> begin...end ©   (01.06.06 14:21) [35]
> Его перекрытию.


Это вряд ли-)

Проверь этот код. Все нормально происходит.

procedure TMyClass.Free;
begin
 ShowMessage('!');
 inherited;
end;


Kolan   (2006-06-01 14:22:00) [24]


> У тебя просто не доходит дело до корректного закрытия доп.
>  потока - система успевает твой дополнительный поток прибить
> раньше.
>

Наконецто вот он ответ..... :). Причина ясна. ;)

Как сделать чтобы дошло?

PS
С кнопками работает.


begin...end   (2006-06-01 14:21:00) [25]

> Пусик ©   (01.06.06 14:19) [34]

> Чему это может помешать?

Его перекрытию.


Пусик   (2006-06-01 14:19:00) [26]


> begin...end ©   (01.06.06 14:19) [32]
> > Пусик ©   (31.05.06 21:26) [13]
>
> > Что в этом особенного?
>
> То, что Free -- он не виртуальный, вообще-то.


И что? Чему это может помешать?


Пусик   (2006-06-01 14:19:00) [27]

Я же сказала тебе основную причину, почему ты не видишь в протоколе твоей точки - это то, что ты пытаешься все это проделать при уничтожении главной формы*читай - главного потока). У тебя просто не доходит дело до корректного закрытия доп. потока - система успевает твой дополнительный поток прибить раньше.

Навесь на кнопки все и проверь.


begin...end   (2006-06-01 14:19:00) [28]

> Пусик ©   (31.05.06 21:26) [13]

> Что в этом особенного?

То, что Free -- он не виртуальный, вообще-то.


Kolan   (2006-06-01 14:16:00) [29]

procedure TMainForm.FormDestroy(Sender: TObject);
begin
 FReadThread.Terminate;
 FComm.Free;
 FPackageComposer.Free;
 FPackageExtractor.Terminate;
 FPackageExtractor.Resume;

end;

Вот код закрытия формы.


Пусик   (2006-06-01 14:12:00) [30]


> Ясно, почему тогда сюда не попадает?


А ты выполнил Terminate перед Resume?


Kolan   (2006-06-01 14:12:00) [31]

37 14:11:25 Suspend
Последняя запись в логе...


Kolan   (2006-06-01 14:11:00) [32]


>
> Поток проснется на выполнении следующей команды после той,
>  которую закончил выполнять перед усыплением.

Ясно, почему тогда сюда не попадает?


>    //
>      LogManager.WriteString('Break');
>      //
>        Break;


Пусик   (2006-06-01 14:11:00) [33]

Если ты выполнял Resume, то выполнение продолжится со след. команнды.
В твоем примере это if Terminated then


Пусик   (2006-06-01 14:09:00) [34]


> Так а где он проснется?


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


Kolan   (2006-06-01 14:09:00) [35]

while not Terminated do
 begin

   if ReadIndex >= WriteIndex then
   begin
     //
     LogManager.WriteString('Suspend');
     //
     Suspend;(*)
     if Terminated then
     begin
       //
     LogManager.WriteString('Break');
     //
       Break;
     end;
   end
   else
   begin
{...}
   end;
 end;
end;

Вот код. Если уснул в (*) и сделать Resume, то где он проснется?


Kolan   (2006-06-01 14:07:00) [36]

Ну уснул.
Перед закрытием
 FPackageExtractor.Terminate;
FPackageExtractor.Resume;


Так а где он проснется?


Пусик   (2006-06-01 14:03:00) [37]


> Из лога видно что уснул и сё...

Ключевая фраза -

> Ставлб BreakPoint перед закрытием приложения


Kolan   (2006-06-01 14:02:00) [38]

if ReadIndex >= WriteIndex then
   begin
     Suspend;
     if Terminated then
     begin
       Break;
     end;
   end


Мой код наналогичный. До Break не добрался, проверял....

PS
Лишние begin..end'ы для отладки .....
Из лога видно что уснул и сё...


Пусик   (2006-06-01 14:00:00) [39]


> По идее должен попрасть в начало Execute:


Не должен, так как выполнение продолжается с места остановки потока.


Пусик   (2006-06-01 13:59:00) [40]


> Что я сделел не так?


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

 if ReadIndex >= WriteIndex then
 begin
    Suspend;
    if Terminated then Break;
 end;


Страницы:   1 2 3

Наверх

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