Обновление данных на диалоге из отдельного потока
От: Аноним  
Дата: 08.06.07 09:57
Оценка:
Есть диалоговое окно,
нужно на нем регулярно отображать информацию из отдельного потока.
Сделал так — кинул на диалог Static Text, связал с ним переменную CString.
после присвоения ей нужного значения делаю Диалогу UpdateData(FALSE).
Если делать из отдельного потока то вываливаеться на UpdateData(FALSE) асерт

Как победить проблемку ?
Re: Обновление данных на диалоге из отдельного потока
От: GRiA  
Дата: 08.06.07 10:49
Оценка:
Удалено избыточное цитирование. — SchweinDeBurg

Здравствуйте, Аноним, Вы писали:

А>Как победить проблемку ?


Вместо UpdateData посылай сообщение, а в обработчике уже вызывай UpdateData
Re[2]: Обновление данных на диалоге из отдельного потока
От: Master Gekus Россия  
Дата: 09.06.07 02:47
Оценка:
Удалено избыточное цитирование. — SchweinDeBurg

Здравствуйте, GRiA, Вы писали:

GRA>Вместо UpdateData посылай сообщение, а в обработчике уже вызывай UpdateData


Да уж... Из серии "из пушки по воробьям"... Если речь о потоках — то либо связываем с контролом не CString, а CStatic, и непосредственно вызываем SetWindowText, либо вообще напрямую SetDlgItemTetx( IDC_..., );

С уважением,
Заливочкин Евгений

P.S. То же относиться и к прогресс-барам
Re[3]: Обновление данных на диалоге из отдельного потока
От: dcb-BanDos Россия  
Дата: 09.06.07 11:22
Оценка:
Удалено избыточное цитирование. — SchweinDeBurg

Здравствуйте, Master Gekus, Вы писали:

MG>Да уж... Из серии "из пушки по воробьям"... Если речь о потоках — то либо связываем с контролом не CString, а CStatic, и непосредственно вызываем SetWindowText, либо вообще напрямую SetDlgItemTetx( IDC_..., );


может ты не заметил, что это надо делать из другого потока
имхо SendMessage в данном случае лучший вариант
Ничто не ограничивает полет мысли программиста так, как компилятор.
Re[4]: Обновление данных на диалоге из отдельного потока
От: Master Gekus Россия  
Дата: 10.06.07 03:33
Оценка:
Здравствуйте, 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]: Обновление данных на диалоге из отдельного потока
От: Pavel Dvorkin Россия  
Дата: 11.06.07 03:17
Оценка:
Здравствуйте, Master Gekus, Вы писали:

MG>А вызов метода CWnd::SetWindowText — просто напрямую вызывает ::SetWindowText.


Так-то он так, да не совсем.

CWnd::SetWindowText — действительно, можно вызвать. Но вообще-то вызывать методы экземпляра класса, созданного в другом потоке , в MFC в общем случае нельзя. Причина — наличие так называемой карты объектов, которая у каждого потока своя. В этой карте хранится список всех созданных потоком объектов — окон, объектов GDI и т.д. И в большинстве случаев эти методы обращаются к карте, а когда они попытаются обратиться к ней из чужого потока, то и карта будет того потока, а там, как легко понять, этого объекта нет, в результате assert.

Это не говоря уж о том, что MFC отнюдь не потокобезопасна.
With best regards
Pavel Dvorkin
Re[6]: Обновление данных на диалоге из отдельного потока
От: Master Gekus Россия  
Дата: 11.06.07 05:13
Оценка:
Здравствуйте, 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]: Обновление данных на диалоге из отдельного потока
От: Sashaka Россия  
Дата: 11.06.07 07:21
Оценка:
PD>>Это не говоря уж о том, что MFC отнюдь не потокобезопасна.
MG>Конечено! Кто б спорил — но, ещё раз говорю, не надо, чтобы забота о безопасности переходила в паранойю — а то ж как в том анекдоте, где для защиты от СПИДа предлагалось обмотать член 40 слоями бинта с йодом и зелнкой, надеть с десяток презервативов — и, главное, никаких половых контактов!

Любой SendMessage из потока окну созданному в другом потоке это потенциальный дедлок.

Лучше перестраховаться — сейчас у вас SetDlgItemText, а завтра требования поменяются и надо будет делать что-то более сложное с окошками (и опасное) из другого потока.
Re[7]: Обновление данных на диалоге из отдельного потока
От: Pavel Dvorkin Россия  
Дата: 13.06.07 07:16
Оценка:
Здравствуйте, Master Gekus, Вы писали:

MG>Как говаривали отцы-основоположники, "марксизм не догма, а руководство к действию". И карта объетов есть, и в каждом потоке своя (слава богу, за 15 лет было время в исходниках покопаться)... Но вот только обращение к ней происходит отнюдь не всегда. Вобщем можно сказать так: небезопасно вызывать функции, которые используют методы группы FromHandle, FromHandlePermanent — остальные вполне безопасно, т.к. они не заморачиваясь обращаются к WinAPI...


Я позволю себе с этим принципом не согласиться. Строго говоря, исходники MFC не есть "документированное поведение". Микрософт вполне может что-то в них поменять в следующей версии, и что тогда ?
With best regards
Pavel Dvorkin
Re[5]: Обновление данных на диалоге из отдельного потока
От: dcb-BanDos Россия  
Дата: 13.06.07 07:55
Оценка:
Исправлено форматирование текста. — SchweinDeBurg

Здравствуйте, Master Gekus, Вы писали:

Я конечно не знаю, но что может быть проще, чем слать свое сообщение и в основном потоке его обрабатывать....
Т.е:

LRESULT MainDialog::OnMyMessage(....)
{
     тут меняем все что надо....
}
Ничто не ограничивает полет мысли программиста так, как компилятор.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.