Malaja
|
|
« : 07-06-2005 15:57 » |
|
схема следующая : f1 { for (i =0; i < Count; i++) ::PostMessage(Msg_Reg) --> }
| | | | \/
dll_2:
class1::f2 (Msg_Reg) { ::PostMessage(Msg_Hlp) }
| | \/ class2::f3(Msg_Hlp) { if (m_hMutex == NULL) createMutex (m_hMutex)
nResOfWait = WaitForSingleObject(m_hMutex, INFINITE); switch(nResOfWait) { case WAIT_OBJECT_0: if (NULL == m_pSsshow) { f4(); }
if (m_pSsshow) { // chto-to delaem } releaseMutex(); break;
} }
class2::f4() { // rabota s registrom // chto-to eshhe m_pSsshow = new ...; m_pSsshow->Start...; }
Смысл - обе dll - и сидят в одном приложении (exe), при этом одна dll посылает другой информацию для последующего отображения.Для отображения используется приложение_2. Как только dll_2 получает инфу, она проверяет, было ли запущено приложение_2 - если да, то данные посылаются дальше, если нет, то сначала его надо запустить. Проблема заключается в том, что все посланные Msg_Hlp градом сыпятся на функцию f3. при этом если приложение_2 было уже запущено,то проблем не возникает и функция успевает отослать инфу дальше. Если же надо сначала запустить приложение, то тут-то и наступает неприятность - f3() вызывает для запуска функцию f4(), а в это время прилетает очередное сообщение Msg_Hlp, в результате: 1) f4() не успевает завершить свою работу, 2) m_pSsshow еще = NULL (во всяком случае таким его видит наша f3() в момент прихода сообщения Msg_Hlp), что уже в корне неверно; 3) при этом почему-то WaitForSingleObject возвращает WAIT_OBJECT_0, посему мы идем на вызов f4()! А это влечет за собой ошибку! Вопрос - что тут не так??? Единственное, что можно было бы поменять, так это PostMessage na SendMessage, но не хочется...
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
RXL
|
|
« Ответ #1 : 07-06-2005 18:17 » |
|
Если m_pSsshow равен NULL, значит выражение, результат выполнения которого будет присвоен m_pSsshow, еще не завершило работу, или результат - NULL. В первом случае, если другой поток обращается к тем же переменным, что и первый, который сейчас висит в f4(), то он должен заблокироваться на мутексе. Видимо, при входе в f3() он видит, что и m_hMutex равен NULL.... Во втором случае см. что делает код m_pSsshow = new ...; Правда при этом следующая строка должна сгенерировать исключение...
Расставь в ключевых точках вывод куда-либо с указанием каких-нибудь данных, по которым можно было бы определить последовательность запуска и поток. Напр. статическая переменная с инкрементом и номер потока.
|
|
« Последнее редактирование: 07-06-2005 18:21 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Malaja
|
|
« Ответ #2 : 08-06-2005 11:55 » |
|
RXL, поставила вокруг trace - ы, результат ну оочень странный... : на одном компе все ок, т.е. все как и было задумано, а на втором - все смешалось в доме облонских / мутексов... , т.е. мутекс создается при первом требовании и далее m_hMutex != 0, при этом следующий вызов функции f3(Msg_Hlp) приводит к тому, что WaitForSingleObject(m_hMutex, INFINITE) возвращает WAIT_OBJECT_0, хотя предыдущий заход еще не окончен и длкя него еще не было вызова releaseMutex().
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
RXL
|
|
« Ответ #3 : 08-06-2005 12:15 » |
|
Проверь метод храниния m_hMutex - как я понимаю, это должен быть static member.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Malaja
|
|
« Ответ #4 : 08-06-2005 12:19 » |
|
это была моя первая идея - не спасает ... а главное, как может существующий мутекс при WaitForSingleObject(m_hMutex, INFINITE) возвращать WAIT_OBJECT_0, если для него еще не вызваны ReleaseMutex и CloseHandle??? Ведь он должен быть до этих пор заблокирован!
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
RXL
|
|
« Ответ #5 : 08-06-2005 12:54 » |
|
Лучше проверь, а только ли в первый раз m_hMutex равен NULL?
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Malaja
|
|
« Ответ #6 : 08-06-2005 12:57 » |
|
да, потом он всегда чему-то равен
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
RXL
|
|
« Ответ #7 : 08-06-2005 19:48 » |
|
Как-то фаталистически звучит...
Если я чувствую, что ничего не понимаю, то я расставляю печать (неважно как - главное чтобы сразу в лог попадало) до подозреваемых проверок и после (желательно во всех вариантах: if - else, switch). Мне помогает. Вывожу там значение самых важных параметров, идентификацию точки и, если надо, процесса/потока и значения проверяемых переменных). Как правило, ошибка бывает глупая и очень глупая, но иногда и думать приходится. Попробуй - может и тебе поможет.
Кстати, чем отличается та, "вторая" машина? Часом не hyperthreading?
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Malaja
|
|
« Ответ #8 : 09-06-2005 07:00 » |
|
Это не просто фаталистически, это уже иронично - плачевно Во-первых, машины ничем, кроме скорости, не отличаются - одна новая, вторая -старая, но на обеих стоит XP. Далее, я сделала всюду traces, которые идут в log - file, чтобы можно было это отследить. Результат - mutex здоров и != 0, при этом WaitForSingleObject почему-то дает доступ к заблокированным ресурсам,хотя заблокировавший их thread их еще не освободил... Я уже пробовала имя mutexa менять на что-то уж точно никогда ранее не встречавшееся - не помогло... Что еще можно было бы вывести для контроля в этой ситуации - не знаю...
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
RXL
|
|
« Ответ #9 : 09-06-2005 08:39 » |
|
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Malaja
|
|
« Ответ #10 : 09-06-2005 11:50 » |
|
я с этого начала - все еще раз прочитала, но ответа не нашла... что меня несколько сбивает столку, так это фраза в описании WaitForSingleObject: "The handle must have the SYNCHRONIZE access right". Я никак не пойму, где его можно установить. Если сделать в лоб: LPSECURITY_ATTRIBUTES lpMutexAttributes; lpMutexAttributes = (LPSECURITY_ATTRIBUTES) malloc(sizeof(SECURITY_ATTRIBUTES)); lpMutexAttributes->nLength = (DWORD) sizeof(SECURITY_ATTRIBUTES); lpMutexAttributes->lpSecurityDescriptor = (LPVOID) SYNCHRONIZE; lpMutexAttributes->bInheritHandle = (BOOL) FALSE;
// create / open m_hMutex = CreateMutex(lpMutexAttributes, FALSE, pMutexName);
то m_hMutex = 0. Т.е. таким образом не катит. А где еще это можно сделать - ума не приложу...
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Chaa
|
|
« Ответ #11 : 10-06-2005 08:15 » |
|
Если все, что работает с мьютексом, в одном процессе, то о правах доступа можно не беспокоиться. Попробуй создать мьютекс не в class2::f3(), а раньше, перед тем как начнут поступать сообщения.
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #12 : 10-06-2005 11:48 » |
|
да я тоже раньше так думала, а теперь я уже ничего не знаю ;-( Я специально хотела после каждого использования мутекса его уничтожать, т.к. мне заранее неизвестно, сколько сообщений надо будет обработать. А держать мутех до следующего использования не хотелось. Но попробовать можно. Тут просто проблема в том, что для теста надо попасть на тестовую установку, которая периодически умирает Сейчас как раз эта ситуация Как только попробую - сообщу о результатах.
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Chaa
|
|
« Ответ #13 : 14-06-2005 03:34 » |
|
Судя по коду, функция class2::f3() вызывается из цикла сообщений, который принимает сообщения от PostMessage(). Если это так, то сообщения ставятся в очередь и выбираются в цикле сообщений функцией GetMessage() по-одному. Поэтому надобности в мьютексах как бы и нет. Вообще, Windows самостоятельно управляет блокировками для оконных процедур, так, чтобы все поступающие сообщения обрабатывались последовательно.
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #14 : 14-06-2005 06:47 » |
|
Chaa,
все это так, но проблема в том, что функция f3() работает довольно долго (а точнее, долго работает f4(), вызываемая из f3), а в этот момент приходит уже следующее сообщение, т.е. мы попадаем в неприятную ситуацию - первый вызов еще не отработан, а второй уже пришел. Так что без мутекса уже никак... Я это проверяла, когда мутекс начал давать на этой машине сбои.
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Chaa
|
|
« Ответ #15 : 14-06-2005 06:59 » |
|
А как получаются сообщения? Насколько я понимаю Windows, если во время обработки первого сообщения придет следующее, оно будет поставлено в очередь и будет находиться там до тех пор пока не будет оработано первое сообщение.
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #16 : 14-06-2005 09:19 » |
|
если они находятся в одном thread-е - да. А тут thread-ы различны, посему сообщения и приходят не по очереди (в смысле очередности обработки), а хаотически.
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Diletant
Помогающий
Offline
|
|
« Ответ #17 : 16-06-2005 13:32 » |
|
А почему не попробовать создать не просто мьютех, а именованный мьютех. Тогда хоть можно быть уверенным, что используется один мьютех. А так нет никакой гарантии, что не создается несколько мьютексов. ИМХО при такой схеме больше CRITICAL_SECTION подходит.
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #18 : 17-06-2005 11:49 » |
|
Diletant,
а он и так именованный, но все равно не помогает ;-( Такое впечатление, что у машины какой-то сбой в мозгах... А другой тестовый комп я пока выцарапать не могу - тут тоже все жадные...
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Diletant
Помогающий
Offline
|
|
« Ответ #19 : 17-06-2005 15:59 » |
|
Если он именованный, то зачем создавать его "в процессе"? Лучше создать заранее, при инициализации приложения, когда еще нет мультипоточности, а затем открывать. А то создание мьютекса в функции потока может порождать очень забавные эффекты. И сравнение переменной с NULL помогает далеко не всегда.
|
|
|
Записан
|
|
|
|
Earnest
Гость
|
|
« Ответ #20 : 17-06-2005 16:07 » |
|
Мне кажется, что решение переусложнено. Если всего лишь надо запретить повторное вхождение в функцию из разных потоков, пока она не завершила работу, то CRITICAL_SECTION - это то, что надо. Инициализировать ее, конечно надо раньше... А что касается разной работы на разных компах, так тоже понятно - немного разные условия, временнЫе задержки... Наверняка даже на одном компе можно получить разные результаты, если по разному нагрузить систему.
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #21 : 20-06-2005 07:58 » |
|
Diletant, большое спасибо за совет - я этого раньше не знала. Вот тебе и "хороший мальчик мутекс из хорошей семьи" Earnest , большое спасибо за совет - попробую.
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Chaa
|
|
« Ответ #22 : 21-06-2005 10:42 » |
|
Решение действительно неоправдано усложнено. Необходимости в блокировках в данном случае нет вообще, так как сообщения будут приходить по-очереди. Не важно, из какого потока они посылаются. PostMessage всегда ставит сообщение в очередь, из которой поток, обрабатывающий сообщения, извлекает их по-одному. В подкрепление моих слов цитата из книги "Programming Windows" by Charles Petzold This process is obviously complex, but fortunately most of the complexity is Windows' problem rather than our program's. From the perspective of the window procedure, these messages come through in an orderly and synchronized manner. The window procedure can do something with these messages or ignore them.
When I say that messages come through in an orderly and synchronized manner, I mean first that messages are not like hardware interrupts. While processing one message in a window procedure, the program will not be suddenly interrupted by another message.
|
|
« Последнее редактирование: 20-12-2007 20:26 от Алексей1153++ »
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #23 : 22-06-2005 10:33 » |
|
Chaa,
спасибо за инфу!
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #24 : 22-06-2005 13:41 » |
|
Вообщето - мютекс не надо так использовать.... Сингл обджект предназначен больше для семафоров и критикал секшнс. Мютекс - уже сам объект - который работает для мультипл (многократных) обращений к нему... Теперь начинаем аккуратно входить в дело и понимаем следующее... Есть объект CMutex http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_Multithreading.3a_.How_to_Use_the_Synchronization_Classes.aspДля того что бы закрыть вход в нужную область кода НЕ НАДО вызывать WaitForSingleObject необходимо вызывать Lock с указанием какой мютекс используется... Мютекс имеет счетчик объектов и сам отслеживает очередность обращения к нему... Т.е. имеем код который надо защитить (в вопросе место обработки сообщения) CMutex ppp; Мютекс создан где то и глобально. ppp.Lock(); код для защиты ppp.Unlock(); Теперь при входе в лок секцию мютекс выставит 1 в счетчик и запустит функцию в работу. Если потом кто-то обратится в это же место, то получится вызов Lock второй раз - который уже заблокирует проход и поднимет каунтер +1. Так до тех пор пока Анлок не спустит каунтер -1 после завершения работы первым процессом. И впустит второй проход который инициирован следующим запрашивавшим и т.д. Так чта ждать не надо.
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Malaja
|
|
« Ответ #25 : 23-06-2005 06:40 » |
|
Гром, это я попробовала сразу и тут же выяснила, что оно почему-то не работало ;-( (я вставляла трейсы, т.к. при дебаге рискуешь не увидеть картинку целиком). Т.е. при следующем вызове Lock() ничего не держал и код начинал выполняться параллельно несколькими threads... Поэтому я решила использовать старый способ (т.е. тот код, который я и привела тут наверху), ишодя из того, что тут я все организую сама. Почему не работало - я объяснить не могу, не знаю. Я долго искала ответ на этот вопрос, потом плюнула и поставила тот самый код. Хотя если я правильно понимаю, класс CMutex содержит именно то, что я сделала сама. Причем что меня совсем цбило с толку, так это то, что этот код (с CMutex) не работал на обеих машинах - моей рабочей и тестовой! А старый проверенный код ( - я его забрала из старого прекрасно живущего с-проекта ) не работал только на тестовой машине! Дурдом какой-то!
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #26 : 23-06-2005 08:39 » |
|
Malaja - код который я предложил работает на 200% - так как я его испытывал даже на СЕ такой вот винде.
Работа Мютексов - работа многопотоковых систем не двух, а много, отсюда каждый мютекс может либо разрешать нескольким одновременно либо запрещать... Стоит тебе перечитать и скачав пример от мелкомягких посмотреть на их реализацию...
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Malaja
|
|
« Ответ #27 : 23-06-2005 10:40 » |
|
Гром,
поняла, спасибо за инфу. Почитаю еще раз, может я что-то еще не установила (флаги или какую-то другую ерунду). Поскольку то, что я вижу, гощорит о том, что мой мутекс разрешает работу одновременно нескольким thread-ам.
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
|