Продолжение проблемы с Threads
От: allco Лес http://www.asdevel.com
Дата: 15.10.04 16:15
Оценка:
Проблема состоит в следующем:

Неудается корректно завершить 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);
в деструкторе класса (мне тогда корректное завершение требовалось при завершении процесса),
но сейчас нужно по событию его останавливать и снова пускать
Re: Продолжение проблемы с Threads
От: Кодт Россия  
Дата: 15.10.04 16:33
Оценка:
Здравствуйте, 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... и прокачивай сообщения, которые к тебе приходят.
Перекуём баги на фичи!
Re: Продолжение проблемы с Threads
От: Sergey J. A. Беларусь  
Дата: 15.10.04 16:37
Оценка:
Здравствуйте, allco, Вы писали:

Возможно проблема в этой строке

A> if (pMe->m_bStopThread)


Возможно компилятор соптимизил обращение к этой переменной (например закинул её значение в регистр).
Попробуй объявить так:
volatile bool m_bStopThread;
Re: Продолжение проблемы с Threads
От: Wulf  
Дата: 16.10.04 09:29
Оценка:
Здравствуйте, 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>
Re[2]: Продолжение проблемы с Threads
От: Кодт Россия  
Дата: 18.10.04 07:56
Оценка:
Здравствуйте, 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;
}
Перекуём баги на фичи!
Re[3]: Продолжение проблемы с Threads
От: Sergey J. A. Беларусь  
Дата: 18.10.04 08:44
Оценка:
Здравствуйте, Кодт, Вы писали:

Всё верно. Я просто спешил, и не стал вчитыватся. Поэтому я и посоветовал проверить с volatile — у меня один раз было что-то с потоками и volatile...

Как види я не угадал
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.