Тут появилась такая задача.
На диалоге ProgressCtrl и две кнопки, определяющие в какую сторону двигать прогресс.
т.е. по нажатию на кнопку выполняется следующее:
while(m_progress.GetPos() < progress_max)
{
pCtrl->StepIt(); // В ту или иную сторону
// и какой-то код, например
Sleep(100);
}
В цикле пока значение прогресса не дойдет до крайнего значения.
Естественно, что во время выполнения цикла кнопки не доступны. А надо, чтобы во время движения прогресса можно было кнопками менять его направление.
В решении задачи нужно применить многопоточность.
Создал UI поток. И отправляю в него сообщение по нажатию кнопок
pMyThread->PostThreadMessage(WM_USER+1, (WPARAM)m_progress.m_hWnd, (LPARAM)-1/*направление*/);
Здравствуйте, dandy, Вы писали:
D>Вынеси этот цикл в рабочий поток.
В потоке придется сделать синхронизацию, например перед запуском нового потока убивать старый, если он запущен и т.п. И в качестве прарметра обычно выгоднее всего передавать указатель на оконный класс, в котором находятся нужные тебе контролы.
Здравствуйте, dandy, Вы писали:
D>В потоке придется сделать синхронизацию, например перед запуском нового потока убивать старый, если он запущен и т.п. И в качестве прарметра обычно выгоднее всего передавать указатель на оконный класс, в котором находятся нужные тебе контролы.
Спасибо, уже сделал через рабочий поток.
Но тут возникла проблема.
В потоке я жду двух событий: по одному (ManualReset) я двигаю прогресс, а по второму выхожу из потока (AfxEndThread(0); )
А в основном потоке при выходе делаю:
Здравствуйте, KokS, Вы писали:
KS>В потоке я жду двух событий: по одному (ManualReset) я двигаю прогресс, а по второму выхожу из потока (AfxEndThread(0); ) KS>А в основном потоке при выходе делаю:
В этом случае синхронизировать лучше примерно так:
Перед созданием нового потока проверять, не работает ли уже предыдущий, проще всего по указателю на объект CWinThread, который делаешь членом класса и инициализируешь нулем в конструкторе, при создании потока присваиваешь ему возврат функции AfxBeginThread. Если указатель не нулевой, событие, по которому выходишь из потока, устанавливаешь в сигнальное состояние, какое — то время ждешь установки указателя в 0 функцией потока, выходишь из функции потока при установленном событии, при выходе из потока устанавливаешь указатель в 0. Можно еще кой — чего добавить, но для этого случая должно быть достаточно.
Здравствуйте, dandy, Вы писали:
D>В этом случае синхронизировать лучше примерно так: D>Перед созданием нового потока проверять, не работает ли уже предыдущий, проще всего по указателю на объект CWinThread, который делаешь членом класса и инициализируешь нулем в конструкторе, при создании потока присваиваешь ему возврат функции AfxBeginThread. Если указатель не нулевой, событие, по которому выходишь из потока, устанавливаешь в сигнальное состояние, какое — то время ждешь установки указателя в 0 функцией потока, выходишь из функции потока при установленном событии, при выходе из потока устанавливаешь указатель в 0. Можно еще кой — чего добавить, но для этого случая должно быть достаточно.
Хочется понять, почему не работает мой вариант.
И как ждать установки указателя в 0? В цикле? Не красиво.
Здравствуйте, KokS, Вы писали:
KS>Здравствуйте, dandy, Вы писали:
KS>Хочется понять, почему не работает мой вариант.
Судя по всему, ты запускаешь поток при создании диалога. Запускай по нажатию кнопки, с предварительной проверкой и последующим убийством уже запущенного потока — если он уже запущен, конечно.
KS>И как ждать установки указателя в 0? В цикле? Не красиво.
Напиши Sleep(сколько_нужно) один раз. Некрасиво — да. Красиво будешь писать тогда, когда сможешь писать и красиво и правильно.
Здравствуйте, dandy, Вы писали:
D>Здравствуйте, KokS, Вы писали:
KS>>Здравствуйте, dandy, Вы писали:
KS>>Хочется понять, почему не работает мой вариант. D>Судя по всему, ты запускаешь поток при создании диалога. Запускай по нажатию кнопки, с предварительной проверкой и последующим убийством уже запущенного потока — если он уже запущен, конечно.
На создание/завершение потока тратиться много процессорного времени, поэтому часто (как в моем случае) этого лучше не делать. Мне как раз и надо, чтобы поток создавался при создании диалога и при закрытии завершался.
KS>>И как ждать установки указателя в 0? В цикле? Не красиво. D>Напиши Sleep(сколько_нужно) один раз. Некрасиво — да. Красиво будешь писать тогда, когда сможешь писать и красиво и правильно.
Так ведь я хочу научиться писать красиво и правильно. Потому и спрашиваю
Здравствуйте, KokS, Вы писали:
KS>На создание/завершение потока тратиться много процессорного времени, поэтому часто (как в моем случае) этого лучше не делать. Мне как раз и надо, чтобы поток создавался при создании диалога и при закрытии завершался.
При обработке нажатия на кнопку это время пренебрежимо мало.
KS>Так ведь я хочу научиться писать красиво и правильно. Потому и спрашиваю
Тогда смотри WaitForSingleObject на хендл убиваемого потока.
D>//В обработчике: D>if(this->pThread_) D>{
// Забыл написать: тут нужно выставить событие hEvent в сигнальное состояние D>if(WaitForSingleObject(pThread->m_hThread, сколько_надо) != WAIT_OBJECT_0) D>{ D> AfxMessageBox(m_hWnd, _T("Failed to kill thread normally, there will be a memory leaks")); D> TerminateThread(this->pThread_->m_hThread) this->>pThread_ = 0; D>} D>}
Здравствуйте, KokS, Вы писали:
KS>Обьясните, пожалуйста, почему. Я просто хочу понять...
Насколько понял, в потоке дорабатывает до этой строки:
dwEvent = WaitForMultipleObjects(2, pst->hEvents, FALSE, INFINITE);
и, как там и написано, останавливается и бесконечно долго ждет. Если непонятно, воспользуйся дебаггером.
Здравствуйте, dandy, Вы писали:
D>Здравствуйте, KokS, Вы писали:
KS>>Обьясните, пожалуйста, почему. Я просто хочу понять...
D>Насколько понял, в потоке дорабатывает до этой строки: D>dwEvent = WaitForMultipleObjects(2, pst->hEvents, FALSE, INFINITE); D>и, как там и написано, останавливается и бесконечно долго ждет. Если непонятно, воспользуйся дебаггером.
Но я же выставляю событие ExitEvent (оно же pst->hEvents[1])
По нему поток и должен завершаться.