![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как правильно удалить поток в различных ситуациях
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;