Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Работа с СWinThread


Автор: Dreamer_0x01 17.8.2005, 18:20
Есть переменная типа CWinThread;
Завершаю программу способом "по флагу остановки"
То есть в процедуре потока есть фича вида
Код

while(!my_flag)
{
/*
Выполняем какие-то действия.
Действия могут выполняться до 1 секунды.
*/
}


Ну а в мое классе есть фича вида
Код

BOOL MyDialog::DestroyWindow()
{
my_flag=TRUE;
return CDialog::DestroyWindow();
}


Cуть проблемы в том, что период опроса флага достаточно большой. И если получается так, что мой основной поток уже зарылся, а тот еще продолжает работать, то выдается ошибка о неосвобождении памяти. Если же в основном потоке после присвоения переменной my_flag поставить Sleep(1010), то ошибка исчезает. Но это некрасиво, надо точно знать, сколько времени на завершение потока понадобится.
Поэтому хотелось бы знать функцию, которая вернет состояние потока, и ждать, пока поток не завершится самостоятельно, а уже потом убивать главное окно.
Пробовал ждать с помощью синхронизации - при запуске рабочего потока входить в критическую секцию, и выходить при завершении потока. А в главном потоке в DestroyWindow после установки флага завершения потока входить в эту же критическую секцию, тем самым усыпляя поток до момента выхода из критической секции второго потока. Работает, но как придется, то есть все равно какие-то доли секунды уходят на накладные расходы, за которые успевает закрыться основной поток. Здесь тоже помогало использование Sleep(10), но сами понимаете, что это некрасивый выход. Короче, надо как-то узнавать состояние потока. Причем уверен, что это просто. Но не знаю, какой функцией пользоваться.

Автор: JoyEx 18.8.2005, 09:15
GetExitCodeThread() или можно ждать на HANDLE - WaitForSingleObject()

Если CWinThread с автоудалением, то тогда CWinThread * может быть недействительным.

Автор: Dreamer_0x01 18.8.2005, 11:04
JoyEx
GetExitCodeThread() почему-то не работает, функция всегда STILL_ACTIVE.
Вот мой код:

Код

/*Wrtd - указатель на поток, полученный при AfxBeginThread()*/
    DWORD TEMP;
    BOOL b;
    HANDLE hnd=HANDLE(*this->Wtrd);
    do
    {
        b=::GetExitCodeThread(hnd,&TEMP);
    }
    while(TEMP==STILL_ACTIVE);


А Конструкция вида
Код

WaitForSingleObject(hnd,10000);

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

Автор: JoyEx 18.8.2005, 15:00
Цитата(Dreamer_0x01 @ 18.8.2005, 11:04)
JoyEx
GetExitCodeThread() почему-то не работает, функция всегда STILL_ACTIVE.

ну да, это же ведь Get - ExitCode - Thread smile пока поток жив, а когда он завершится, то тогда и получишь то, что вернет его управл. ф-ция
И потом, надо дублировать HANDLE потому, что его может закрыть сам CWinThread или CWinThread::m_bAutoDelete = FALSE

Цитата(Dreamer_0x01 @ 18.8.2005, 11:04)
А Конструкция вида
код C++
1:
WaitForSingleObject(hnd,10000);

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


В MSDN пишут:
The WaitForSingleObject function can wait for the following objects:
  • Change notification
  • Console input
  • Event
  • Job
  • Memory resource notification
  • Mutex
  • Process
  • Semaphore
  • Thread
  • Waitable timer
Из HANDLE Thread WaitForSingleObject() узнает жив ли еще поток, не событие это вовсе

Автор: Dreamer_0x01 18.8.2005, 15:22
Цитата

ну да, это же ведь Get - ExitCode - Thread  пока поток жив, а когда он завершится, то тогда и получишь то, что вернет его управл. ф-ция


В том то и дело, что у меня поток уже завершился, а в TEMP все равно STILL_ACTIVE сидит...

Автор: JoyEx 18.8.2005, 15:35
Dreamer_0x01
Проверь, что вернула ф-ция + еще неплохо бы инициализировать TEMP

У тебя наверное первый раз ф-ция записала в TEMP STILL_ACTIVE, а потом туда ничего не писАла, а ты не проверял что (наверное, ЛОЖЬ) она возвращала.

Автор: Dreamer_0x01 18.8.2005, 16:33
JoyEx

Нет, смотрел в отладчике, функция всегда 1 возвращала.

А вот инициализация TEMP помогла!!! Видать, она этот кусок кода как-то соптимизировала по-своему. Теперь если перед вызовом функции обнулять TEMP, то все работает как надо.

Но все равно мне больше понравился метод с WaitForSingleObject. Так вроде бы даже грамотнее, не только проще.

Автор: Coocky 18.8.2005, 16:44
Dreamer_0x01
Цитата
А вот инициализация TEMP помогла!!!

Ты в "семерке" работаешь?

Автор: Dreamer_0x01 18.8.2005, 22:58
Coocky
Цитата

Ты в "семерке" работаешь?


Да

Автор: Coocky 19.8.2005, 10:32
Dreamer_0x01
Теперь понятно, откуда такое отношение к инициализации.
Надеешься на студию smile
Я еще с шестерки ВСЕГДА сам инициализирую переменные.Столько проблем решается.. smile

Автор: Dreamer_0x01 19.8.2005, 12:45
Coocky
А можешь пояснить, почему?

Автор: Coocky 19.8.2005, 15:51
Dreamer_0x01
Цитата
А можешь пояснить, почему?

А ты не инициализируй, и пройдись в отладке через переменную.. smile

Автор: Dreamer_0x01 19.8.2005, 18:17
Ну это-то понятно, что там мусор будет.
Но если она используется в функции, в которой все равно изменится ее значение - то зачем предварительная инициализация нужна?

Автор: Coocky 22.8.2005, 11:03
Dreamer_0x01
Цитата
Но если она используется в функции, в которой все равно изменится ее значение - то зачем предварительная инициализация нужна?

smile
Ну дык откуда ты знаешь, что она не пользуется значением, передаваемым в функцию где-то внутри этой функции? smile
То что она возвращает значение по ссылке, еще не чего не значит.. smile
Может внутри есть такое..

Код

switch (TEMP)
{
case ... : ...... ;
case ... : ...... ;
case ... : ...... ;
case ... : ...... ;
default :...............;

}


А если ТЕМР мусор, то что передал , то и получишь smile
Во всяком случае поверь моему опыту (хоть и маленькому)smile


Автор: Dreamer_0x01 22.8.2005, 16:06
Цитата
Во всяком случае поверь моему опыту (хоть и маленькому)

Ладно те пребедняться smile

Цитата

Может внутри есть такое..
Код 
switch (TEMP)
{
case ... : ...... ;
case ... : ...... ;
case ... : ...... ;
case ... : ...... ;
default :...............;
}

А если ТЕМР мусор, то что передал , то и получишь


Хорошо,но как тогда узнать, какими значениями можно инициализировать TEMP, а какими нельзя? Ведь в хелпе этого не сказано... А в исходниках искать подобные вещи как-то не привлекает.

Автор: Coocky 22.8.2005, 21:18
Dreamer_0x01

Цитата
Хорошо,но как тогда узнать, какими значениями можно инициализировать TEMP, а какими нельзя? Ведь в хелпе этого не сказано... А в исходниках искать подобные вещи как-то не привлекает.

smile
Ты видищь- я опять улыбаюсь! А это означает твою невнимательность smile
Еще раз за параметр TEMP из МСДН. ТО что нужно я віделю:
Цитата
  Pointer to a 32-bit variable to receive the thread termination status.

Вопросы?
Я думаю, присваивать нуль указателю при инициализации-есть очень хорошая и ПРАВИЛЬНАЯ традиция smile

Автор: Dreamer_0x01 24.8.2005, 12:33
С указателем согласен. Но распространяется ли это на "обыкновенные" переменные?

Автор: Coocky 24.8.2005, 12:39
Dreamer_0x01
Цитата
Но распространяется ли это на "обыкновенные" переменные?

В смысле? smile

Отвлекаешь старика от работы... smile
Сделал тест
Код

int z;

 Test (&z);
//////////////////////////////////
////Проходим бебагером
void CtestDlg::Test(int* p)
{int *a=p;
int g=*a;////g= -858993460 :) 
}

или так
Код

int z;

 Test (&z);
//////////////////////////////////
////Проходим бебагером
void CtestDlg::Test(int* p)
{
int g=*p;////g= -858993460 :) 
}


Я думаю, когда делали семерки, много аспектов учли smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)