PDA

Просмотр полной версии : Потоки (Threads) и окна.



AiK
29.09.2004, 02:27
Можно ли в отдельном потоке создать постоянно живущее окно?
Если я ещё где-то не напортачил, то имею такую ситуацию: окно, созданное в отдельном потоке, прекращает своё существование вместе с завершением потока.
Спасибо за ответ.

Kolinus
29.09.2004, 16:48
Можно.
Во всяком случае под виндами.
Просто фишка втом что насколько я помню винда прибивает поток если убит процесс, породивший твой поток.

окно, созданное в отдельном потоке, прекращает своё существование вместе с завершением потока. - так и надо - мусор-то за собой убирать надо. Поток прекратился значит и ресурсы все свои должен отдать и почистить
Или я чего-то не понял

AiK
29.09.2004, 17:15
Kolinus, процесс, породивший поток продолжает жить. Поток завершается, и вместе сним аннигилируют окна, в нём созданные. Чего я хочу избежать...

Hawk
29.09.2004, 17:33
Конечно можно =)
только чтобы окно работало надо чтобы и поток его породивший работал. Точнее надо создать локальный для потока цикл обработки сообщений в функции потока -

DWORD WINAPI ThreadProc( LPVOID lpParameter )
{
...
hWnd = CreateWindow(...); //создаем окно
...
while (GetMessage(...)) // крутим цико сообщений пока окно не вызовет PostQuitMessage
{
TranslateMessage(...);
DispatchMessage(...);
}
return 0;
}

Eugie
29.09.2004, 17:48
Поток завершается, и вместе сним аннигилируют окна, в нём созданные. Чего я хочу избежать...

Увы, это так. Поток владеет созданными в нем окнами, и при его завершении они уничтожаются. Поэтому если окно должно "жить долго", его обычно создают в главном потоке процесса.

AiK
29.09.2004, 17:53
Жаль. Я надеялся, что в одном потоке можно создать окно, принадлежащее другому. В данном случае главному потоку процесса-родителя.

Kolinus
29.09.2004, 18:00
В Рихтере написано, что ВСЕ созданные потоком объекты разрушаются при его сметри (система ПОЛЬНОСТЬЮ чисти весь его стек)

Kolinus
29.09.2004, 18:03
От создателей Windows на русском ;)
Посмотри AiK - это глава из Рихтера про потоки где все подробно объяснено - мот чем-т поможет
http://softs.h10.ru/literature.shtml?topic=visual&book=1&page=head6.htm

Dragonfly
01.10.2004, 20:18
Можно. Я делал. Но нужны ОЧЕНЬ хорошие права. Для зловредных прог практически не подходит. Суть состоит в использовании CreateRemoteThread() можно создать свой поток хоть в kernel'е. Второй способ (описан или в том же Рихтере или в... а не помню). Называется "Секреты Windows 95" в NT'XP используется подобный механизм. Фактически, твоя прога должна взять на себя функции загрузчика и в ручную загрузить прогу в память. Но в случае NT твоя прога должна быть драйвером.

PS: Второй способ никогда не пробовал.

AiK
02.10.2004, 04:39
Dragonfly, прога сверхзловредная :) - это тулбар для IE. Так что вариант с драйвером не годится. CreateRemoteThread пробовал, разницы с CreateThread никакой не обнаружил. Похоже придётся с окном связывать данные и обновлять по мере получения в потоке...

Dragonfly
04.10.2004, 10:55
AiK, я так понимаю, что если ты создаешь окно в потоке, то так оно и надо (никогда не писал ничего для IE - это реализуется в виде модуля?), но ты уверен, что поток обязательно нужно убивать? Насколько я помню, в подобных случаях, т.е. например при постоянном прослушивании порта, сокета и т.п., я делал так:

void ThreadProc()
{
SetThreadPriority(...);

while(1)
{
}
}

Синтаксис функций не помню точно, сейчас под Linux?ом сижу и MSDN у меня тут нет :)

Т.е. даже если, как я предполагаю, IE сам поток создает, а потом его не убивает до конца своего существования, то можно воспользоваться тем же недостатком - Винда ведь сама все почистит?

AiK
04.10.2004, 13:49
Dragonfly, суть такая - я изначально неправильно стал делать поток. У меня таких потоков последовательно не один десяток будет вызываться, а окно должно быть одно. Так что окно буду создавать в другом потоке, а в этом потоке только данные, связанные с окном обновлять. А вот поток прибивать хотелось бы корректно. Под какой-то виндой можно всего навсего 40 потоков заводить, так что хендлы закрывать придётся. Пока ещё не придумал как. Что-то мне подсказывает, что если в конце ThreadProc вызвать GetCurrentThread, а потом CloseHandle, то ожидаемого эффекта я не получу... Короче, я временно забил на эту задачу - надо теорию поштудировать, а пока времени на это нет :(

Dragonfly
04.10.2004, 14:36
В принципе TerminateThread() вполне корректно убивает поток (с точки зрения системы) если поток в это время не активен. Т.е. запускаешь Sleep(2000) и как-то отмечаешь это состояние "для внешнего мира". Но я вызывал TerminateThread() только из родительского потока.

Eugie
04.10.2004, 17:00
В принципе TerminateThread() вполне корректно убивает поток (с точки зрения системы) если поток в это время не активен.

Вообще-то, TerminateThread() не рекомендуется использовать абы где, т.к. поток она убивает не вполне корректно (в частности, при этом не оповещаются DLL, загруженные в адр.пр-во процесса, не освобождаются некоторые системные ресурсы). Как написано в MSND, использовать ее следует только в исключительных обстоятельствах.

AiK, вообще завершение потока возможно 2 способами: 1) его ThreadProc() завершила свою работу, вызвав return или ExitThread(); 2) поток извне 'попросили' завершиться (например, с помощью TerminateThread). Во втором случае корректная схема должна быть такая: перед созданием потока создаем объект событие (см. CreateEvent), устанавливаем его в несигнальное состояние, посылаем его хэндл 4-м параметром в CreateThread и отслеживаем его состояние с помощью WaitForSingleObject: если состояние сигнальное, вызываем ExitThread. Конечно, по завершении потока его хэндл должен быть освобожден вызовом CloseHandle().

Еще одно замечание: если в потоковой процедуре будут использоваться CRT функции, следует создавать/завершать поток с помощью _beginthreadex()/_endthread().

Kerghan
18.11.2004, 23:47
Знач так.
1. Никаких TerminateThread'ов, так как не освобождается стек потока и не только он.
2. Окна действительно принадлежат потокам, так как в контексте потока находтся все месаги этим окнам, и вслучае смерти потока, окна тоже помирают.
3. Вызывая GetCurrentThread мы получаем псевдо-хэндл. Закрывай его или не закрывай - мало что изменится.
4. СРАЗУ после вызова ht =CreateThread(....) нужно вызывать CloseHandle(ht) - поток это не прибьет, но уменьшится счетчик юзеров потока на 1. Это если не будут потом юзаться различные Wait-ф-ции конечно или SuspendThread. Просто вряд ли хэндл еще понадобится, а забыть его освободить всегда можна, и при завершении потока объект ядра останется до тех пор, пока не завершится весь процесс.
5. Корректно завершить поток можно следующим образом: у нас ведь есть окно. Вот и послать в случае необходимости этому окну какое-то сообщение; в обработчике же можна почиститься и вызвать ExitThread.

Eugie
19.11.2004, 16:36
Kerghan, окно есть только в главном потоке. Поэтому вариант с сообщениями не годится. В данном случае (все потоки в АП одного процесса) можно сделать совсем просто - глобальный массив флагов. Запустил вторичный поток - установил флаг. Надо завершить - сбросил, а в потоковой процедуре отслеживать и вызывать ExitThread.