Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: HWND, WM_USER и новый поток.  (Прочитано 15213 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
Diletant
Помогающий

de
Offline Offline

« : 14-09-2005 11:08 » 

Описание:
Имеется MFC приложение на базе диалога. По нажатию одной из кнопок вызывается фукция, выполняющая достаточно долго сложные вычисления, которые прилично нагружают процессор. Функция не является членом класса диалога, а является частью посторонней библиотеки. Чтобы наблюдать за процессом вычислений в функцию в качестве параметров передаются CALLBACK функция и хендл окна диалога (this->m_hWnd) для посылки сообщений диалогу, в частности ProgressBarу. Все отлично функционирует пока функция вычислений вызывается непосредственно из функции-члена класса диалога.
Но захотелось отделить мух от котлет и осуществлять вычисления в отдельном потоке.  И вот тут начались проблемы. Т.е. сами вычисления осуществляюся как и раньше, но диалог собщений от CALLBACK функции не видит в упор. Если используешь PostMessage, сообщения пропадают не известно где, а если SendMessage, то поток зависает на этом месте навсегда. Хотя хендл диалога передается CALLBACK функции правильно, я проверял.

Вопросы:
Где грабли?
В чем особенности передачи хэндла окна между потоками?
Можно ли в MFC приложениях использоать _beginthreadex или непеременно CreateThread()?
Существует ли другой способ обновлять окно диалога, чтобы он не замирал на веки-вечные, пока не завершатся вычисления?
« Последнее редактирование: 14-09-2005 11:11 от Diletant » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 14-09-2005 11:43 » 

приеди код, как передаёшь хендл диалога при запуске потока
Записан

Diletant
Помогающий

de
Offline Offline

« Ответ #2 : 14-09-2005 19:43 » 

Обычный вызов функции:
ulRes =CalculateIt( Param1, 
                     Param2,
                         ...
                     ParamN,
                     MyCallBack,
                     (void*)&(this->m_hWnd),
                     &bStop);


Вызов в новом потоке:
stParam.Param1 = Param1;
stParam.Param2 = Param2;
....
stParam.ParamN = ParamN;
stParam.fnMyCallBack = MyCallBack;
stParam.hWnd =   this->m_hWnd;
stParam.pbStop = &bStop;

hThread = (HANDLE)_beginthreadex(NULL,
                                 0,      
                                 (PTHREAD_START) ProcessThread,
                                 (void*)&stParam,
                                 0,
                                 &uiThrdaddr
                                );

unsigned int ProcessThread(void* pParam)
{
 unsigned int uiRes = 0;
 LPDLGPARAM   pDatas = (LPDLGPARAM) pParam;

 uiRes = CalculateIt( pDatas->Param1,
                        pDatas->Param2,
                          ...
                        pDatas->ParamN,
                        pDatas->fnMyCallBack,   
                        (void*)&(pDatas->hWnd),
                        pDatas->pbStop
                      );


 return uiRes;
}


Еще раз повторю, хендл приходит тот же самый, я проверял.
« Последнее редактирование: 14-09-2005 19:48 от Diletant » Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #3 : 14-09-2005 20:21 » 

Цитата
Можно ли в MFC приложениях использоать _beginthreadex или непеременно CreateThread()
Рихтер пишет
Цитата
Чтобы многопоточные программы, использующие библиотеку С/С++, работали корректно, требуется создать специальную структуру данных и связать ее с каждым потоком, из которого вызываются библиотечные функции Более того, они должны знать, что, когда Вы к ним обращаетесь, нужно просматривать этот блок данных в вызывающем потоке чтобы не повредить данные в каком-нибудь другом потоке

Так откуда же система знает, что при создании нового потока надо создать и этот блок данных? Ответ очень прост не знает и знать не хочет Вся ответственность — исключительно на Вас Если Вы пользуетесь небезопасными в многопоточной среде функциями, то должны создавать потоки библиотечной функцией _begmthreadex, а не Windows-функцией CreateThread
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Diletant
Помогающий

de
Offline Offline

« Ответ #4 : 14-09-2005 20:36 » 

Во-первых, Рихтер там дальше (толи на этой же странице, то ли на следующей ) пишет, что CreateThread() можно таки вполне безопасно использовать. Да и сам набор слов: "Если Вы пользуетесь небезопасными в многопоточной среде функциями" выглядит неоднозначно.
Во-вторых, я наверное не совсем удачно сформулировал. Вопрос должен был звучать так: Есть ли какие-либо специфические особенности  использования  нескольких потоков в MFC приложениях?
Записан
Diletant
Помогающий

de
Offline Offline

« Ответ #5 : 14-09-2005 20:40 » 

PS. Относится функция SendMessage() к опасным или к безопасным?
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #6 : 14-09-2005 20:55 » 

Я сейчас искал в книге. Но не нашел. Но думаю, что у потока создается своя очередь сообшений. И любые посылы сообшения окну приходят именно в данную очередь. PostMessage просто ложит сообшение в очередь и дает дальше работать. SendMessage же вызывает работу дальше по обработке сообшения. Сама по себе функция безопасна.
Кстати у Рихтера написано. Что есть целый ряд функции библиотеки С/С++, для которых лучше использовать _begmthreadex. Иначе возможен вылет программы или утечка данных.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #7 : 14-09-2005 21:04 » 

Попробуй сделать объект ядра "событие" с автозакрытием. В окне поставь WaitForSingleObject для ожидания открытия. А в потоке периодически открывай событие.
Функции CreateEvent, OpenEvent, SetEvenT, CloseHandle. Минус в этом вижу только, что окно не будет перересоваться, если его закрыть, а затем открыть.
« Последнее редактирование: 14-09-2005 21:06 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Diletant
Помогающий

de
Offline Offline

« Ответ #8 : 15-09-2005 08:34 » 

Так как обойти возникшую ситуацию я придумать смогу, но непонятно, почему не работает самый казалось бы очевидный вариант. Помнится, в свое время, Гром утверждал, что правильнее всего под Windows для каждого процесса создавать окно, пусть невидимое, и все межпроцессорное общение вести через сообщения. А тут внутри одного процесса почему-то сообщения не пашут.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #9 : 26-10-2005 13:05 » new

Может уже поздно, но я нашел у Рихтера место про очереди сообшений. Мои подозрения подтвердились. Для каждого потока сушествует своя очередь сообшений. Чтобы поместить сообшение в очередь конкретного потока сушествует функция PostThreadMessage. Чтобы объединить очереди есть функция AttachThreadInput
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines