Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.138.105.31] |
|
Сообщ.
#1
,
|
|
|
В диалоговом приложении запускается поток (AfxBeginThread), который в цикле опрашивает web-сервис и выводит на форму некоторую информацию.
При закрытии основной формы в событии OnClose устанавливаю флаг завершения потока (он в цикле потоковой функции проверяется) и жду завершения потока (WaitForSingleObject), а функция потока в этот момент еще парсит длинный ответ сервера и пытается вывести информацию в контрол на форме. На строчке обращения к переменной-члену, связанному с контролом всё зависает. Перед обращением к этой переменной, конечно, можно проверять установлен или нет флаг завершения потока, но всё-таки интересно, почему всё зависает, ведь в событии OnClose (когда получено сообщение WM_CLOSE), все члены класса диалога еще существуют. Как сделать правильно? |
Сообщ.
#2
,
|
|
|
Зависает, скорее всего потому, что у тебя поток посылает сообщение, синхронное, контролу (при помощи SendMessage), однако в это время обрабатывается тоже синхронное сообщение WM_CLOSE, которое ждёт завершения потока. В результате - дедлок.
В потоке нужно посылать сообщение при помощи PostMessage. |
Сообщ.
#3
,
|
|
|
Ну, я использую стандартные контролы и их стандартные методы, CListCtrl, в частности... Заниматься переопределением, думаю, нецелесообразно. Оставил проверку на флаг завершения потока перед обращением к контролам. Спасибо!
|
Сообщ.
#4
,
|
|
|
Цитата yasli @ Заниматься переопределением, думаю, нецелесообразно. Целесообразно и правильно. Все методы у CListCtrl всего лишь обёртки над SendMessage, посмотри их реализацию. Их нельзя вызывать в другом потоке. Цитата yasli @ Оставил проверку на флаг завершения потока перед обращением к контролам. Спасибо! Это не поможет. Дедлок будет возникать реже, но регулярно. Всегда пожалуйста. |
Сообщ.
#5
,
|
|
|
Цитата Олег М @ Цитата yasli @ Заниматься переопределением, думаю, нецелесообразно. Целесообразно и правильно. Все методы у CListCtrl всего лишь обёртки над SendMessage, посмотри их реализацию. А как/где посмотреть их реализацию? |
Сообщ.
#6
,
|
|
|
Цитата yasli @ А как/где посмотреть их реализацию? В исходниках. Например D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\include\afxcmn.inl |
Сообщ.
#7
,
|
|
|
А может быть такое, что какое-нибудь сообщение, отправленное с пом. PostMessage придёт уже после того, как окно, которому оно отправлено, будет уничтожено? Могут ли возникать утечки памяти в этом случае? И как их избежать, если могут?
|
Сообщ.
#8
,
|
|
|
Цитата yasli @ ..и жду завершения потока (WaitForSingleObject), а функция потока в этот момент еще парсит длинный ответ сервера и пытается вывести информацию в контрол на форме. А пусть она (функция потока) делает это не так. Не надо выводить информацию на контрол из потока. Пусть поточная функция пошлёт информацию оконной процедуре посредством "PostMessage" заранее обусловленным сообщением. А уже оконная процедура раздаёт информацию контролам. --- Если в какой-то момент окно получит WM_CLOSE, обработчик этого сообщения может просто логически "отключить" функционал обработчика сообщений с данными. И никаких "коллизий" не будет. Например, попытки работать с уже уничтоженными контролами. При такой логике работы можно будет заменить работу с WM_CLOSE работой с WM_DESTROY. |
Сообщ.
#9
,
|
|
|
Цитата yasli @ А может быть такое, что какое-нибудь сообщение, отправленное с пом. PostMessage придёт уже после того, как окно, которому оно отправлено, будет уничтожено? Могут ли возникать утечки памяти в этом случае? И как их избежать, если могут? Без разницы. Сообщение просто не обработается и всё, никаких утечек не будет. Проблемы могут возникнуть по другой причине - там в большинство сообщении нужно отправлять адреса структур. Т.к. сообщение посылается асинхронно, через PostMessage, нужно как-то гарантировать, что эти структуры будут ещё живы на момент обработки. Цитата ЫукпШ @ Не надо выводить информацию на контрол из потока. Пусть поточная функция пошлёт информацию оконной процедуре посредством "PostMessage" заранее обусловленным сообщением. А уже оконная процедура раздаёт информацию контролам. Да, примерно так. Сохраняешь данные в какой-нибудь переменной класса, После изменения их в потоке делаешь PostMessage(WM_USER......) В обработчике этого WM_USER.... вызываешь нужные методы CListCtrl. Либо можно, наверное, использовать SendMessageTimeout для отправки сообщений из потока |
Сообщ.
#10
,
|
|
|
Цитата Олег М @ Проблемы могут возникнуть по другой причине - там в большинство сообщении нужно отправлять адреса структур. Т.к. сообщение посылается асинхронно, через PostMessage, нужно как-то гарантировать, что эти структуры будут ещё живы на момент обработки. Очень просто. Между потоком и оконной процедурой организуем потоко-безопасную очередь. Например, указателей на структуры данных. Если структуры невелики по размеру, можно очередь структур. Поток выделяет память для структуры. Заносит данные в структуру, указатель размещает в очередь, посылает уведомление оконной процедуре (WM_APP + xx). В самом сообщении можно вообще не пересылать никаких данных. Или пересылать какой-либо признак, характеризующий данные, если вариантов данных много. Но это по-вкусу. После этого поток забывает об обработанных уже данных и готов к получению новых. Оконная процедура в обработчике сообщений проверяет наличие данных в очереди, извлекает их, если имеются, преобразует/раздаёт, ликвидирует структуру. |
Сообщ.
#11
,
|
|
|
Цитата Олег М @ Цитата yasli @ А как/где посмотреть их реализацию? В исходниках. Например D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\include\afxcmn.inl Там, похоже, не все функции содержатся. Не нашел CListCtrl::GetItemText и CListCtrl::SetItemText. Где они еще могут быть?.. |
Сообщ.
#12
,
|
|
|
Цитата yasli @ см в winctrl2.cpp |
Сообщ.
#13
,
|
|
|
Большое всем спасибо!
|