Есть диалоговое окно,
нужно на нем регулярно отображать информацию из отдельного потока.
Сделал так — кинул на диалог Static Text, связал с ним переменную CString.
после присвоения ей нужного значения делаю Диалогу UpdateData(FALSE).
Если делать из отдельного потока то вываливаеться на UpdateData(FALSE) асерт
Как победить проблемку ?
Re: Обновление данных на диалоге из отдельного потока
Здравствуйте, GRiA, Вы писали:
GRA>Вместо UpdateData посылай сообщение, а в обработчике уже вызывай UpdateData
Да уж... Из серии "из пушки по воробьям"... Если речь о потоках — то либо связываем с контролом не CString, а CStatic, и непосредственно вызываем SetWindowText, либо вообще напрямую SetDlgItemTetx( IDC_..., );
С уважением,
Заливочкин Евгений
P.S. То же относиться и к прогресс-барам
Re[3]: Обновление данных на диалоге из отдельного потока
Здравствуйте, Master Gekus, Вы писали:
MG>Да уж... Из серии "из пушки по воробьям"... Если речь о потоках — то либо связываем с контролом не CString, а CStatic, и непосредственно вызываем SetWindowText, либо вообще напрямую SetDlgItemTetx( IDC_..., );
может ты не заметил, что это надо делать из другого потока
имхо SendMessage в данном случае лучший вариант
Ничто не ограничивает полет мысли программиста так, как компилятор.
Re[4]: Обновление данных на диалоге из отдельного потока
Здравствуйте, dcb-BanDos, Вы писали:
MG>>Да уж... Из серии "из пушки по воробьям"... Если речь о потоках — то либо связываем с контролом не CString, а CStatic, и непосредственно вызываем SetWindowText, либо вообще напрямую SetDlgItemTetx( IDC_..., );
DB>может ты не заметил, что это надо делать из другого потока DB>имхо SendMessage в данном случае лучший вариант
Ну, вообще-то, я не тормоз, я медленный газ... И на подобные вещи внимание обращаю...
SetWindowText собственно и вызывает SendMessage( WM_SETTEXT, ... ); У уж SendMessage сама переключиться в нужный поток (из Remarks по SendMessage):
If the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code.
А адресное пространство у потоков общее — так что и с этим проблем нет... Да и если в другой поток отправлять — тоже не есть смаое страшное, так как отдублирует система копию строки в адресное пространство другого процесса.
А вызов метода CWnd::SetWindowText — просто напрямую вызывает ::SetWindowText.
Вобщем, можно, конечно, и двухуровневую схему закрутить — но получиться то же самое, только через двойной вызов SendMessage. Работать-то будет, конечно. Но вот лучший ли это вариант? Тут я уже не уверен...
И в Вашем, и в моём случае происходит переключение в контекст другого потока и блокировка вызывающего до завершения обработки — только у Вас на один SendMessage больше, и существенно больше кода, плюс, видимо, придётся заводить какое-то своё сообщение для обмена с основным потоком. Чтобы не блокировать вызывающий, можно было бы воспользоваться PostMessage — но тут уже нужно создавать копию текста, т.к. неизвестно, что станет с оригиналом, пока дело дойдёт до его обработки в основном потоке.
Хотя, конечно, потренироваться в подобных вещах не вредно — ну, на будущее...
С уважением,
Заливочкин Евгений
P.S. Подобную фишку (интерфейсный диалог и поток, выполняющий длительное дейстие) пишу на автомате года этак с 95-го... Пришлось даже вспоминать, почему так делаю и не задумываюсь. Еще раз убедился, что не со зла . Спасибо — иногда полезно вспоминать хорошо забытое старое...
P.P.S. — А вообще-то всё это в Рихтере было!
Re[5]: Обновление данных на диалоге из отдельного потока
Здравствуйте, Master Gekus, Вы писали:
MG>А вызов метода CWnd::SetWindowText — просто напрямую вызывает ::SetWindowText.
Так-то он так, да не совсем.
CWnd::SetWindowText — действительно, можно вызвать. Но вообще-то вызывать методы экземпляра класса, созданного в другом потоке , в MFC в общем случае нельзя. Причина — наличие так называемой карты объектов, которая у каждого потока своя. В этой карте хранится список всех созданных потоком объектов — окон, объектов GDI и т.д. И в большинстве случаев эти методы обращаются к карте, а когда они попытаются обратиться к ней из чужого потока, то и карта будет того потока, а там, как легко понять, этого объекта нет, в результате assert.
Это не говоря уж о том, что MFC отнюдь не потокобезопасна.
With best regards
Pavel Dvorkin
Re[6]: Обновление данных на диалоге из отдельного потока
Здравствуйте, Pavel Dvorkin, Вы писали:
MG>>А вызов метода CWnd::SetWindowText — просто напрямую вызывает ::SetWindowText. PD>Так-то он так, да не совсем.
PD>[...] Но вообще-то вызывать методы экземпляра класса, созданного в другом потоке , в MFC в общем случае нельзя. Причина — наличие так называемой карты объектов, которая у каждого потока своя. [...]
Как говаривали отцы-основоположники, "марксизм не догма, а руководство к действию". И карта объетов есть, и в каждом потоке своя (слава богу, за 15 лет было время в исходниках покопаться)... Но вот только обращение к ней происходит отнюдь не всегда. Вобщем можно сказать так: небезопасно вызывать функции, которые используют методы группы FromHandle, FromHandlePermanent — остальные вполне безопасно, т.к. они не заморачиваясь обращаются к WinAPI... Даже пресловутую SetDlgItemText можно вызывать — тоже напрямую к API обращается (если у нас не OLE-контейнер), безо всяких карт... А вот функций типа GetWindow, GetDC, DDX_*, Attach и тому подобные, которые приводят к обращениям к картам объктов — это да, тут можно и по морде получить...
PD>Это не говоря уж о том, что MFC отнюдь не потокобезопасна.
Конечено! Кто б спорил — но, ещё раз говорю, не надо, чтобы забота о безопасности переходила в паранойю — а то ж как в том анекдоте, где для защиты от СПИДа предлагалось обмотать член 40 слоями бинта с йодом и зелнкой, надеть с десяток презервативов — и, главное, никаких половых контактов!
С уважением,
Заливочкин Евгений
Re[7]: Обновление данных на диалоге из отдельного потока
PD>>Это не говоря уж о том, что MFC отнюдь не потокобезопасна. MG>Конечено! Кто б спорил — но, ещё раз говорю, не надо, чтобы забота о безопасности переходила в паранойю — а то ж как в том анекдоте, где для защиты от СПИДа предлагалось обмотать член 40 слоями бинта с йодом и зелнкой, надеть с десяток презервативов — и, главное, никаких половых контактов!
Любой SendMessage из потока окну созданному в другом потоке это потенциальный дедлок.
Лучше перестраховаться — сейчас у вас SetDlgItemText, а завтра требования поменяются и надо будет делать что-то более сложное с окошками (и опасное) из другого потока.
Re[7]: Обновление данных на диалоге из отдельного потока
Здравствуйте, Master Gekus, Вы писали:
MG>Как говаривали отцы-основоположники, "марксизм не догма, а руководство к действию". И карта объетов есть, и в каждом потоке своя (слава богу, за 15 лет было время в исходниках покопаться)... Но вот только обращение к ней происходит отнюдь не всегда. Вобщем можно сказать так: небезопасно вызывать функции, которые используют методы группы FromHandle, FromHandlePermanent — остальные вполне безопасно, т.к. они не заморачиваясь обращаются к WinAPI...
Я позволю себе с этим принципом не согласиться. Строго говоря, исходники MFC не есть "документированное поведение". Микрософт вполне может что-то в них поменять в следующей версии, и что тогда ?
With best regards
Pavel Dvorkin
Re[5]: Обновление данных на диалоге из отдельного потока