| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > WaitForSingleObject лочит тред? |
| Автор: mrgloom 9.7.2012, 12:27 | ||||||||||
| такое ощущение, что WaitForSingleObject в основном процессе блокирует выполнение кода в созданном треде. т.е. я например делаю
хочу чтобы тред остановился ,а тред должен выставить ивент когда закончится.
и ожидаю
или так
но такое ощущение, что в треде после вызова WaitForSingleObject ничего не происходит вообще, т.е. это даже не связано с ивентами, пробовал даже левый тестовый ивент- результат тот же.
причем если WaitForSingleObject убрать, то в тред нормально заходит и ::SetEvent(m_StopThread); и условие тоже нормально схватывает. но мне надо не просто отправить команду треду завершится но еще и подождать пока завершится тред. |
| Автор: Randajad 9.7.2012, 12:40 |
| (std|boost)::thread и не пишите платформозависимый код. |
| Автор: baldina 9.7.2012, 13:28 |
| у WaitForSingleObject второй параметр - время ожидания. Вам, по видимому туда надо передавать константу INFINITE. Если передается 0, то WaitForSingleObject ничего не ждет, а сразу возвращает текущее состояние. Однако хотелось бы увидеть возвращаемое значение, Вы его нигде не анализируете, а оно может быть разным. Например WAIT_FAILED. Были ли m_StopThread и m_WaitThread созданы при помощи CreateEvent() ? |
| Автор: Randajad 9.7.2012, 16:34 |
| std::atomic в помощь. Делаете, скажем, булевую переменную - выставляете ее в true, если надо прервать. В цикле в потоке проверяете ее. |
| Автор: mrgloom 9.7.2012, 16:47 | ||||||
| попробовал буст+ булевые переменные в классе так запускаю
так останавливаю
в теле треда
и всё равно на while(!m_WaitThread) всё виснет и в треде почему то ничего не выполняется. Добавлено @ 16:49 не заметил ответа, пока писал. std::atomic? в каких то источниках пишут еще volatile bool, а простая булевая переменная таит в себе какие то опастности? Добавлено @ 16:58 попробовал volatile bool результат тот же. а std::atomic это же что то новое как и std::thread, не? |
| Автор: feodorv 9.7.2012, 23:09 | ||||||
Честно говоря, так не делается. Ибо тред выставляет ивент и на этом не заканчивается. Например, если поток вызван из подключенной dll, а Вы по состоянию события решаете, что поток завершился и отключаете dll от процесса, то велика вероятность получить нарушение доступа. Дескриптор потока - тоже синхронизирующий объект, поэтому вполне можно его ожидать:
Я не понял, какой именно... Да и вообще не понятно, что происходит в программе (в основном потоке и в созданном). У Вас есть возможность сбрасывать логи, так почему бы ей не воспользоваться? Вставьте в проблемные части кода немного выдачи, да проанализируйте её... Я вот, например, не уверен, что
хоть когда-нибудь вернёт WAIT_OBJECT_0.... А если возвращает, то почему не выдаёт ??? Или выдаёт? Короче, нужны подробности, ничего не ясно... |
| Автор: mrgloom 10.7.2012, 09:29 | ||||||
| ну да можно без ивента попробовал так. постоянно WAIT_TIMEOUT, в теле треда никакой активности.
я выше написал как вызываю, есть кнопка на форме старт и пауза, на старт тред начинает исполнение, на паузу выставляется ивент остановить тред, который на каждой итерации в цикле треда проверяется, потом надо дождатся когда тред закончится и вот тут то и вылезает проблема, т.к. всё зависает на WaitForSingleObject. может это как то связано с формой? или ивент каким то образом лочится? причем если без WaitForSingleObject, то ивент в треде нормально определяется и тред завершается, только получается основной поток его не ждет. Добавлено через 14 минут и 45 секунд хммм попробовал
и в тред управление приходит только после выполнения слипа, а то и вообще после выполнения всего кода по кнопке пауза, т.е. такое ощущение, что приоритет у основного треда выше и управление не передается. |
| Автор: mrgloom 10.7.2012, 09:49 | ||
попробовал так, всё тоже самое, изменение приоритета не помогает.
|
| Автор: baldina 10.7.2012, 11:32 | ||
запустите такую программку
result в обоих случаях должен быть равным 0 (это и есть WAIT_OBJECT_0) |
| Автор: feodorv 10.7.2012, 11:58 |
А что за функция? Как описана? |
| Автор: mrgloom 10.7.2012, 12:56 | ||
попробовал
и всё сработало и меня натолкнуло на мысль а не попробовать ли CControlDlg::GetFrame без класса и попробовал и оно заработало ,а теперь остается вопрос, почему когда функция внутри класса, то она не работает? может это связано с тем что если объявлять в классе, то для передачи в AfxBeginThread её надо объявлять как static? а может заработало потому что я ивенты объявил глобально, а не в классе? функция CControlDlg::GetFrame сейчас там просто цикл с слипом для тестирования, типа имитация работы, начальное значения от куда начинать цикл берется из класса. |
| Автор: baldina 10.7.2012, 13:09 |
| CControlDlg::GetFrame вызывалась без объекта? тогда просто повезло, что оно не плюхнулось. |
| Автор: feodorv 10.7.2012, 13:15 | ||||
Если функция описана внутри класса, то она неявно имеет ещё один аргумент. В результате
превращается в
Вызывалось, так как первым аргументом AfxBeginThread шла функция, а в этом случае AfxBeginThread не знает, что она из какого-то класса... Компилятор, кстати, должен бы выдать предупреждение... |
| Автор: mrgloom 10.7.2012, 15:54 | ||||
ну и какой из этого вывод?
так я ж говорю ,что AfxBeginThread ест только статик, когда передаешь функцию из класса, а статик функцию вроде как можно и без объекта вызывать. хотя, если функция не из класса можно и не статик её передавать. |
| Автор: feodorv 10.7.2012, 16:06 |
Так у Вас был статик или не статик? |
| Автор: mrgloom 10.7.2012, 16:20 | ||||||
у меня был статик, когда функция была в классе, а без класса я статик не использовал и всё и так скомпилировалось. но я поспешил радоватся, ибо я попробовал на простом примере.
но когда я пытаюсь добавить обновление чисел на форме, всё опять виснет на WaitForSingleObject (который по кнопке пауза)
т.е. такое ощущение что это что то связано с механизмом работы DoDataExchange |
| Автор: feodorv 10.7.2012, 16:37 | ||
А там наверняка сообщения в оконную процедуру используются? Так нельзя же тогда пользоваться простыми Wait-функциями, ибо тогда очередь сообщений не обрабатывается. Пользуйтесь MsgWaitForMultipleObjects... Добавлено через 1 минуту и 19 секунд И ещё:
|
| Автор: mrgloom 10.7.2012, 17:11 | ||||
не очень понял, MsgWaitForMultipleObjects это вроде как не к тредам, а к сообщениям относится? раньше использовал, такой набросок найденный в сети, но честно говоря, не очень понимаю как это всё работает, потом решил переписать через треды, получается тут через треды нельзя? и меня не устроило, то что этот код хорошо работает, только если у нас итерация цикла маленькая, а так пользователю надо потстоянно жать на кнопку отмена(чтобы не пропустить момент), а надо нажал, программа подождала пока завершится текущая итерация(забокировав гуи).
|
| Автор: baldina 10.7.2012, 17:25 | ||
|
| Автор: feodorv 10.7.2012, 17:35 | ||||
Можно.
Не просто к сообщениям, а в том числе и к тем, которые обновляют форму. Вот кусок кода, который ждёт завершения потока, одновременно обрабатывая сообщения:
Добавлено через 1 минуту и 8 секунд Ой, пока искал код, baldina уже всё написал |
| Автор: mrgloom 11.7.2012, 10:48 |
| спасибо, всё заработало. только с теоретической точки зрения непонятно, почему сообщения лочили выполнение кода в треде. |
| Автор: baldina 11.7.2012, 10:51 |
| они не лочили. просто окошко "подвисло", т.к. управляется сообщениями, а они не проходили. теперь мы их обработали, и стало все ок |