Проблема состоит в следующем:
Неудается корректно завершить Thread,
функция WaitForSingleObject(m_pThread->m_hThread, INFINITE), зависает на бесконечное количество времени,
при этом трид не дохнет и не выполняется НЕ ПРОИСХОДИТ НИ ЧЕГО (прога просто зависает)
Почему это происходит?
Как решить проблему?
void CThreadTroubleDlg::OnGoThread()
{
m_pThread = AfxBeginThread(ThreadProc, this, THREAD_PRIORITY_LOWEST);
CStatic* pText = (CStatic*)GetDlgItem(IDS_TEXT);
TRACE(_T("\nThread is started!"));
pText->SetWindowText(_T("Thread is started!"));
}
void CThreadTroubleDlg::OnStopThread()
{
m_bStopThread = TRUE;
// Вот сдесь весь геморрой и сосредеточен!
if (m_pThread != NULL) WaitForSingleObject(m_pThread->m_hThread, INFINITE);
CStatic* pText = (CStatic*)GetDlgItem(IDS_TEXT);
TRACE(_T("\nThread is dead!"));
pText->SetWindowText(_T("Thread is dead!"));
}
UINT CThreadTroubleDlg::ThreadProc(LPVOID lParam)
{
CThreadTroubleDlg* pMe = (CThreadTroubleDlg*)lParam;
CStatic* pText = (CStatic*)pMe->GetDlgItem(IDS_TEXT);
ASSERT(pText);
while(1)
{
if (pMe->m_bStopThread)
{
TRACE(_T("\nThread is stopped!\n\n"));
pText->SetWindowText(_T("Thread is stopped!"));
break;
}
else
{
TRACE(_T("\nThread is alive!"));
pText->SetWindowText(_T("Thread is alive!"));
}
}
return 0;
}
Тестовый проект можно скачать здесь:
http://allco.simtel.ru/ThreadTrouble.rar
login: rsdn
passwd: rsdn
P.S. Данный вопрос уже подымался мной пару месяцев назад, решение было найдено в вызове WaitForSingleObject(m_pThread->m_hThread, INFINITE);
в деструкторе класса (мне тогда корректное завершение требовалось при завершении процесса),
но сейчас нужно по событию его останавливать и снова пускать
Здравствуйте, allco, Вы писали:
A>Неудается корректно завершить Thread,
A>функция WaitForSingleObject(m_pThread->m_hThread, INFINITE), зависает на бесконечное количество времени,
A>при этом трид не дохнет и не выполняется НЕ ПРОИСХОДИТ НИ ЧЕГО (прога просто зависает)
A>Почему это происходит?
A>Как решить проблему?
Понятно почему!
В главном потоке ты обрабатываешь сообщение OnStopThread, взводя флажок и далее ожидая сигнал.
Начиная с этого момента главный поток виснет...
Рабочий поток, увидев флаг, посылает главному потоку сообщение SendMessage(... WM_SETTEXT ...)
pText->SetWindowText(_T("Thread is dead!"));
и ждёт, когда же тот обработает...
А тот не обрабатывает... кукует...
Мораль:
1) Нефиг вообще из рабочего потока ковыряться в окнах.
2) Нефиг в оконном потоке глухо ждать чего-то
3) Если хочешь ждать — делай MsgWaitFor... и прокачивай сообщения, которые к тебе приходят.
Здравствуйте, allco, Вы писали:
A>
A>UINT CThreadTroubleDlg::ThreadProc(LPVOID lParam)
A>{
A> CThreadTroubleDlg* pMe = (CThreadTroubleDlg*)lParam;
A> CStatic* pText = (CStatic*)pMe->GetDlgItem(IDS_TEXT);
A> ASSERT(pText);
A> while(1)
A> {
A> if (pMe->m_bStopThread)
A> {
A> TRACE(_T("\nThread is stopped!\n\n"));
A> //pText->SetWindowText(_T("Thread is stopped!"));
pText->PostMessage(WM_SETTEXT, NULL, (LPARAM)_T("Thread is stopped!"));
A> break;
A> }
A> else
A> {
A> TRACE(_T("\nThread is alive!"));
A> //pText->SetWindowText(_T("Thread is alive!"));
pText->PostMessage(WM_SETTEXT, NULL, (LPARAM)_T("Thread is alive!"));
A> }
A> }
A> return 0;
A>}
A>
Здравствуйте, Sergey J. A., Вы писали:
SJA>Возможно компилятор соптимизил обращение к этой переменной (например закинул её значение в регистр).
SJA>Попробуй объявить так:
SJA>volatile bool m_bStopThread;
volatile здесь не при чём: компилятор не имеет права "оптимизировать" обращение к внешней переменной, если между моментами обращения есть вызовы внешних функций.
Эффект volatile проявляется в других случаях:
#if 1
// ничего не делаем, честно ждём
#define VOLATILE volatile
#define WORK() void(0)
#elif 1
// занимаемся ерундой, поэтому честно ждём
#define VOLATILE
#define WORK() printf("")
#else
// ничего не делаем, хрен дождёмся (при опции "оптимизация по скорости")
#define VOLATILE
#define WORK() void(0)
#endif
VOLATILE bool broken = false;
void on_ctrl_break(int) { broken = true; }
int main()
{
signal(SIGINT, on_ctrl_break);
printf("press Ctrl+C to stop 100%% CPU usage\n");
while(!broken) WORK();
printf("Ay maladca!\n");
return 0;
}
Здравствуйте, Кодт, Вы писали:
Всё верно. Я просто спешил, и не стал вчитыватся. Поэтому я и посоветовал проверить с volatile — у меня один раз было что-то с потоками и volatile...
Как види я не угадал