На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual C++ / MFC / WTL (далее Раздела)
1) На Раздел распространяются все Правила Форума.
2) Перед тем, как создать новый топик, убедитесь, что Вы читали Правила создания тем в Разделе.
3) Вопросы, не связанные с программированием (настройки MS Visual Studio, книги, библиотеки и т.д.),
обсуждаются в разделе C/C++: Прочее
4) Вопросы разработки .NET (Windows Form, C++/CLI и т.п.) приложений на Visual C++/C# обсуждаются в разделе .NET.
5) Нарушение Правил может повлечь наказание со стороны модераторов.

Полезные ссылки:
user posted image FAQ Раздела user posted image Обновления для FAQ Раздела user posted image Поиск по Разделу user posted image MSDN Library Online
Модераторы: ElcnU
  
> В какой момент уничтожаются члены класса диалога?
    В диалоговом приложении запускается поток (AfxBeginThread), который в цикле опрашивает web-сервис и выводит на форму некоторую информацию.
    При закрытии основной формы в событии OnClose устанавливаю флаг завершения потока (он в цикле потоковой функции проверяется) и жду завершения потока (WaitForSingleObject), а функция потока в этот момент еще парсит длинный ответ сервера и пытается вывести информацию в контрол на форме. На строчке обращения к переменной-члену, связанному с контролом всё зависает.
    Перед обращением к этой переменной, конечно, можно проверять установлен или нет флаг завершения потока, но всё-таки интересно, почему всё зависает, ведь в событии OnClose (когда получено сообщение WM_CLOSE), все члены класса диалога еще существуют.
    Как сделать правильно?
    Сообщение отредактировано: yasli -
      Зависает, скорее всего потому, что у тебя поток посылает сообщение, синхронное, контролу (при помощи SendMessage), однако в это время обрабатывается тоже синхронное сообщение WM_CLOSE, которое ждёт завершения потока. В результате - дедлок.
      В потоке нужно посылать сообщение при помощи PostMessage.
        Ну, я использую стандартные контролы и их стандартные методы, CListCtrl, в частности... Заниматься переопределением, думаю, нецелесообразно. Оставил проверку на флаг завершения потока перед обращением к контролам. Спасибо!
        Сообщение отредактировано: yasli -
          Цитата yasli @
          Заниматься переопределением, думаю, нецелесообразно.

          Целесообразно и правильно. Все методы у CListCtrl всего лишь обёртки над SendMessage, посмотри их реализацию. Их нельзя вызывать в другом потоке.


          Цитата yasli @
          Оставил проверку на флаг завершения потока перед обращением к контролам. Спасибо!

          Это не поможет. Дедлок будет возникать реже, но регулярно. Всегда пожалуйста.
            Цитата Олег М @
            Цитата yasli @
            Заниматься переопределением, думаю, нецелесообразно.

            Целесообразно и правильно. Все методы у CListCtrl всего лишь обёртки над SendMessage, посмотри их реализацию.

            А как/где посмотреть их реализацию?
              Цитата yasli @
              А как/где посмотреть их реализацию?

              В исходниках. Например D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\include\afxcmn.inl
                А может быть такое, что какое-нибудь сообщение, отправленное с пом. PostMessage придёт уже после того, как окно, которому оно отправлено, будет уничтожено? Могут ли возникать утечки памяти в этом случае? И как их избежать, если могут?
                  Цитата yasli @
                  ..и жду завершения потока (WaitForSingleObject), а функция потока в этот момент еще парсит длинный ответ сервера и пытается вывести информацию в контрол на форме.

                  А пусть она (функция потока) делает это не так.
                  Не надо выводить информацию на контрол из потока.
                  Пусть поточная функция пошлёт информацию оконной процедуре
                  посредством "PostMessage" заранее обусловленным сообщением.
                  А уже оконная процедура раздаёт информацию контролам.
                  ---
                  Если в какой-то момент окно получит WM_CLOSE, обработчик
                  этого сообщения может просто логически "отключить" функционал обработчика
                  сообщений с данными. И никаких "коллизий" не будет.
                  Например, попытки работать с уже уничтоженными контролами.
                  При такой логике работы можно будет заменить работу с WM_CLOSE
                  работой с WM_DESTROY.
                  Сообщение отредактировано: ЫукпШ -
                    Цитата yasli @
                    А может быть такое, что какое-нибудь сообщение, отправленное с пом. PostMessage придёт уже после того, как окно, которому оно отправлено, будет уничтожено? Могут ли возникать утечки памяти в этом случае? И как их избежать, если могут?

                    Без разницы. Сообщение просто не обработается и всё, никаких утечек не будет.
                    Проблемы могут возникнуть по другой причине - там в большинство сообщении нужно отправлять адреса структур. Т.к. сообщение посылается асинхронно, через PostMessage, нужно как-то гарантировать, что эти структуры будут ещё живы на момент обработки.

                    Цитата ЫукпШ @
                    Не надо выводить информацию на контрол из потока.
                    Пусть поточная функция пошлёт информацию оконной процедуре
                    посредством "PostMessage" заранее обусловленным сообщением.
                    А уже оконная процедура раздаёт информацию контролам.


                    Да, примерно так.
                    Сохраняешь данные в какой-нибудь переменной класса,
                    После изменения их в потоке делаешь PostMessage(WM_USER......)
                    В обработчике этого WM_USER.... вызываешь нужные методы CListCtrl.

                    Либо можно, наверное, использовать SendMessageTimeout для отправки сообщений из потока
                      Цитата Олег М @
                      Проблемы могут возникнуть по другой причине - там в большинство сообщении нужно отправлять адреса структур. Т.к. сообщение посылается асинхронно, через PostMessage, нужно как-то гарантировать, что эти структуры будут ещё живы на момент обработки.

                      Очень просто.
                      Между потоком и оконной процедурой организуем потоко-безопасную очередь.
                      Например, указателей на структуры данных. Если структуры невелики по размеру,
                      можно очередь структур.
                      Поток выделяет память для структуры. Заносит данные в структуру, указатель
                      размещает в очередь, посылает уведомление оконной процедуре (WM_APP + xx).
                      В самом сообщении можно вообще не пересылать никаких данных.
                      Или пересылать какой-либо признак, характеризующий данные, если вариантов
                      данных много. Но это по-вкусу.
                      После этого поток забывает об обработанных уже данных и готов к получению новых.
                      Оконная процедура в обработчике сообщений проверяет наличие данных в очереди,
                      извлекает их, если имеются, преобразует/раздаёт, ликвидирует структуру.
                      Сообщение отредактировано: ЫукпШ -
                        Цитата Олег М @
                        Цитата yasli @
                        А как/где посмотреть их реализацию?

                        В исходниках. Например D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\include\afxcmn.inl

                        Там, похоже, не все функции содержатся.
                        Не нашел CListCtrl::GetItemText и CListCtrl::SetItemText. Где они еще могут быть?..
                        Сообщение отредактировано: yasli -
                          Цитата yasli @

                          см в winctrl2.cpp
                            Большое всем спасибо!
                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                            0 пользователей:


                            Рейтинг@Mail.ru
                            [ Script execution time: 0,0409 ]   [ 16 queries used ]   [ Generated: 16.04.24, 21:53 GMT ]