Текущий архив: 2004.09.05;
Скачать: CL | DM;
Вниз
Потоки при завершении приложения Найти похожие ветки
← →
Fktrc (2004-08-19 08:08) [0]Подскажите, необходимо ли завершать (методом Terminate) потоки при завершении программы или тут можно положиться на винду?
← →
Думкин © (2004-08-19 08:15) [1]Можно и положиться. ТОлько программ заканчивается когда:
1.
2.
3.
4.
у тебя как?
← →
Digitman © (2004-08-19 08:28) [2]
> Fktrc (19.08.04 08:08)
> методом Terminate
метод Terminate не "завершает" трэд, этот метод всего лишь взводи флаг, информирующий трэд о необходимости как можно более быстрого завершения ... если трэд никак не реагирует на состояние этого флага (не опрашивает его периодически), толку от вызова метода - ноль.
← →
Fktrc (2004-08-19 08:31) [3]//Можно и положиться. ТОлько программ заканчивается когда:
//1.
//2.
//3.
//4.
//у тебя как?
Немного не понял.
У меня так - при завершении все настройки из потоков, ассоциированных с элементами TListView, сохраняются при OnClose и собсно все. Далее в процесс завершения не вмешиваюсь.
Да, у потоков FreeOnTerminate=True.
← →
Рамиль © (2004-08-19 08:55) [4]
> FreeOnTerminate=True.
Означает, что объект уничтожится по окончанию работы, к завершению работы отношения не имеет.
← →
Digitman © (2004-08-19 09:01) [5]
> Fktrc (19.08.04 08:31) [3]
коль скоро у тебя каждый TListItem ассоциирован с индивид.трэдом, есть прямой резон обрабатывая событие TListView.OnDeletion явно разрушать трэд
сделай так :
1. FreeOnTerminate=False для всех существующих трэдов
2. В обработчике TListView.OnDeletion явно вызови деструктор трэда
TMyThread(Item.Data).Free;
это будет достаточно корректным вариантом
← →
Digitman © (2004-08-19 09:04) [6]ну и желательно при этом перенести сохранение настроек трэдов из Form.OnClose в ListView.OnDeletion
← →
Fktrc (2004-08-19 09:09) [7]//Digitman © (19.08.04 09:01) [5]
Вот я и спрашивал, нужно ли при завершении программы явно разрушать треды или можно плюнуть на них - все равно при завершении программы вся выделенная ею память освобождается системой. Просто не хочется при завершении видеть AV. Пока его не случалось, но раз на раз не приходится.
← →
Digitman © (2004-08-19 09:26) [8]
> нужно ли при завершении программы явно разрушать треды или
> можно плюнуть на них
лучше не "плевать" .. намусорил ? убери за собой ! что тут сложного ?
кроме памяти трэд может в ряде случаев использовать и иные ресурсы, например, алгоритм трэда может реализовать контроллер автоматизации для out-of-proc сервера автоматизации (т.е. являющего собой самостоятельный процесс) ... если такой трэд будет принудительно неявно снят с исполнения при завершении твоего процесса, связь с сервером автоматизации будет потеряна и он, будучи не выгруженный как положено, будет продолжать использовать занятые им ресурсы
другой пример - весьма рисковано принудительно снимать с выполнения трэд, активно использующий BDE-сессии
← →
Fktrc (2004-08-19 09:41) [9]2 DigitMan
ОК, понял.
А вот скажи, как лучше организовать взаимодействие с компонентами главной формы из потоков. Я при создании потока передаю ему ссылку на соответствующий TListItem (как в учебнике). И из потока обращаюсь к нему так: Synchronize (Метод), а процедура Метод содержит следующее
if LI.SubItems[0] <> "Проверка состояния" then
LI.SubItems[0] := "Проверка состояния";
Существует ли лучшее решение, чем это?
← →
Digitman © (2004-08-19 09:50) [10]
> Fktrc (19.08.04 09:41) [9]
а какой конечный тайный смысл алгоритма твоей поточной ф-ции ? в цикле "пасти" изменения значения LI.SubItems[] ? Это все чем занят поток ? Тогда, разумеется, твое существующее решение - далеко не лучшее, если не сказать "корявое" ..
изменить текст сабитема осн.трэд и сам вполне в состоянии сделать ... после чего осн.трэд, если этого требует логика, может известить об этом доп.трэд, ассоциированный с эл-том списка, сабитем которого изменился ...
← →
Fktrc (2004-08-19 10:07) [11]>Digitman © (19.08.04 09:50) [10]
Опишу поподробнее.
Каждый поток в цикле периодически выполняет некоторое действие (интервал между выполнениями задается Sleep). Перед началом выполнения в ListItem надпись меняется на "Проверка состояния", после выполнения надпись в ListItem меняется в зависимости от результата выполненного действия.
Прошу прощения, этот код написан по запарке и сроду не от того элемента свойства ListItem.SubItems[]. Но на самом деле это бывает нужно для того, чтобы ListView не перерисовывался (с мерцанием), если надпись в соответствующем столбце не изменилась со времени предыдущего прохода цикла.
← →
Digitman © (2004-08-19 10:13) [12]
> Fktrc (19.08.04 10:07) [11]
все-таки приведи фрагменты кода ... картина целиком не очень ясна
← →
Erik1 (2004-08-19 10:51) [13]Тебе бы хороший пример по работе с тредами посмотреть. Ненадо использоват Sleep лчше WaitFroMultiObject + Event. И качество твоего кода возрастет. Я например для завершения использую такой метод:
procedure TCustomThread.Stop;
begin
Windows.SetEvent(tmEvent.Event[actExit]);
if Suspended then
Resume;
MsgWaitForSingleObject(Handle);
end;
← →
Fktrc (2004-08-19 11:00) [14]Кода там уже очень много, пробовал вырезать маленькие куски - полная лажа получается (наверное и весь код - лажа, да и сам я ламер :))
Но суть вот в чем:
TItemThread = class(TThread)
private
{ Private declarations }
LI: TListItem;
...
published
constructor Create (ListItem: TListItem);
end;
...
constructor TItemThread.Create (ListItem: TListItem; const Dat: TParam);
begin
inherited Create(true); // Create thread suspended
LI := ListItem;
...
end;
Далее обращение к итему производится вот так
Synchronize (DoSomenthing);
...
procedure TItemThread.DoSomenthing;
begin
if LI.SubItems[1] <> "Текст" then // нужно для того, чтобы ListView не перерисовывался
LI.SubItems[1] := "Текст"; // если текст в столбце не менялся, а то
// список мерцает
end;
Есть ли лучший способ организации взаимодействия с компонентами на форме из вспомогательного потока, кроме как методом Synchronize?
PS:
Если общение с другим потоком происходит путем установки его глобальных переменных в нужные значения, то на ум приходят критические секции и прочее (еще не использовал, но если потребуется, стану разбираться с ними). А вот можно ли использовать критические секции для управления компонентами из другого потока - не знаю.
← →
Fktrc (2004-08-19 11:02) [15]>Erik1 (19.08.04 10:51) [13]
Хорошо бы. Да где его взять.
Если можешь, кинь ссылку на пример. Желательно с такими особенностями:
1. Потоки реализованы на API.
2. Потоки общаются с визуальными компонентами на главной форме.
← →
Digitman © (2004-08-19 11:09) [16]подход с использованием Synchronize() здесь, думаю, чреват дэдлоками, если трэд разрушается явно
можно попробовать посылать окну формы со списком некое предопределенное асинронное (PostMessage) сообщение, при получении которого окно формы выполнит TMyForm.DoSomething (т.е. метод этот в дан.случае следует перенести из класса трэда в класс формы)
← →
Fktrc (2004-08-19 11:34) [17]2 Digitman
Спасибо, попробую.
← →
panov © (2004-08-19 11:47) [18]>Fktrc (19.08.04 08:08)
>Digitman
Хочу чуток уточнить.
После выполнения Free или Destroy поток не уничтожается, а ожидает окончание поточной функции - Execute, "принудительно" его можно уничтожить только прямым вызовом TerminateThread.
← →
Digitman © (2004-08-19 12:06) [19]
> panov © (19.08.04 11:47) [18]
> ожидает окончание поточной функции
ну для меня, положим, это не новость
как раз в Д5 и как раз здесь потенциально возможен дэдлок
цитирую фрагмент WaitFor:
while MsgWaitForMultipleObjects(1, H, False, INFINITE,
QS_SENDMESSAGE) = WAIT_OBJECT_0 + 1 do PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE)
как видим, PeekMessage присутствует, а диспетчеризации сообщения нет ... а ведь SendMessage(), вызванный в контексте Synchronize(), "ждет" обработки посланного сообщения !
> "принудительно" его можно уничтожить только прямым вызовом
> TerminateThread
здесь имелся ввиду не явный вызов TerminateThread(), а
The ExitProcess function ends a process and all its threads.
...
Terminating a process causes the following:
...
2. All of the threads in the process terminate their execution.
← →
Erik1 (2004-08-19 15:01) [20]procedure MsgWaitForSingleObject(Handle: THandle);
begin
repeat
if MsgWaitForMultipleObjects(1, Handle, False, INFINITE, QS_ALLINPUT)
= WAIT_OBJECT_0 + 1
then
Application.ProcessMessages
else BREAK;
until True = False;
end;
← →
atruhin © (2004-08-20 08:58) [21]>Erik1[13]
>Ненадо использоват Sleep
это почему же ?
> Я например для завершения использую такой метод:
и зачем все это? чем это отличается от обычного MyThread.Free?
← →
Digitman © (2004-08-20 09:07) [22]
> atruhin © (20.08.04 08:58) [21]
> это почему же ?
в момент "спячки" трэд не способен ни на что реагировать.. а если "спячка" длится значительное время, и в это время юзеру стукнуло в голову завершить работу приложения ? подумай ...
> чем это отличается от обычного MyThread.Free?
тем что несколько облегчает решение проблемы с потенциально возможными дэдлоками
Страницы: 1 вся ветка
Текущий архив: 2004.09.05;
Скачать: CL | DM;
Память: 0.53 MB
Время: 0.049 c