Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Стоит ли работать с GUI из разных потоков


Автор: Nastya 20.7.2007, 14:48
Вопрос скорее философии, но мнение мэтров действительно важно.
Я всегда считала, что работа с GUI должна всегда идти в одном потоке, если другие потоки хотят влиять на интерфейс, они шлют соотвествующим окнам /интерфейсным потоками сообщения (SendMessage/PostMessage).

Как на вашей практике, при нарушении этого правила, действоиельно возникают проблемы?

Автор: _hunter 20.7.2007, 15:01
правило не нарушал -- проблем не было smile
при нарушении правиал в Builder'е косяки ходили косяками...

Автор: Nastya 20.7.2007, 15:07
_hunter, а в MFC. по идеи оно там тоже не очень защищено? 
Просто я в тягостных раздумьях - переписывать ли мне тот код, который правила нарушает(не мой) или пущай живет :( 
Боюсь, что ленивый делает дважды :(

Автор: _hunter 20.7.2007, 15:52
насколько я знаю -- ни одно GUI не держит многопоточность и эти рекомендации -- общие.
в том же шарпе отладчик сразу же предупреждает если из другого потока обращаться к GUI...

Автор: Earnest 20.7.2007, 16:06
Цитата(Nastya @  20.7.2007,  16:07 Найти цитируемый пост)
а в MFC. по идеи оно там тоже не очень защищено?

Вообще никак не защищено.
Если, скажем, вызвать CDocument::UpdateAllViews() не в главном потоке (точнее, не в том потоке, которому принадлежат эти окна), из ASSERT'ов не вылезешь. Хотя, это тоже можно считать защитой smile  smile  smile 

Я пишу код так, чтобы все обращения к GUI были из главного потока. В критических местах ставлю 
ASSERT(AfxGetApp()==AfxGetThread());

Кстати, Invalidate из потока вполне можно вызвать...

Добавлено через 1 минуту и 10 секунд
Цитата(Nastya @  20.7.2007,  16:07 Найти цитируемый пост)
переписывать ли мне тот код, который правила нарушает(не мой) 

Если есть возможность - перепиши. Особенно, если не нравится.

Автор: Nastya 20.7.2007, 16:12
Цитата

Кстати, Invalidate из потока вполне можно вызвать...


ну, этот по-любому только мессадж выставит, а рисовсть-то он уже в интерфейсном потоке будет.

Я просто грустно созерцаю SetWindowText(...) из другого потока.
Как-то... представила что в это рвемя кто-то (тот же OnPaint) делает GetWindowTextLenght + GetWindowText ..... 
В общем...
Мэтрам. спасибо и респект smile 

Автор: Earnest 20.7.2007, 17:39
Цитата(Nastya @  20.7.2007,  17:12 Найти цитируемый пост)
Я просто грустно созерцаю SetWindowText(...) из другого потока.

Кстати, вполне может прокатить (только не MFC-версия, а WinAPI): эта функция посылает WM_SETTEXT, которая в любом случае будет обрабатываться в потоке окна, и проблем с WM_PAINT не будет.
Сообщение WM_SETTEXT можно послать даже другому процессу, чего уж о потоке беспокоиться.

Но с точки зрения мировой гармонии, удачнее дизайн, когда к окну не получает доступ кто попало, а окно (панель или кто там у тебя) само лазит в свои поля и их обновляет, в главном потоке, естественно. А "кто попало" всего лишь выставляет флаг изменения (и ровно ничего про окно не знает). 

Автор: Nastya 23.7.2007, 09:56
Earnest, Ну вот, я только уверелась в своей правоте smile
А чем MFC SetWindowText отличется от API варианта ? (просто инетерсно). вроде тоже все самое 

Автор: zkv 23.7.2007, 10:12
Цитата(Nastya @  23.7.2007,  09:56 Найти цитируемый пост)
А чем MFC SetWindowText отличется от API варианта ?

Код

//afxwin2.inl
_AFXWIN_INLINE void CWnd::SetWindowText(LPCTSTR lpszString)
    { ASSERT(::IsWindow(m_hWnd)); ::SetWindowText(m_hWnd, lpszString); }

Автор: Earnest 24.7.2007, 16:30
Ну, конкретно MFC::SetWindowText может и из потока прокатит. Но во многих функциях MFC сначала ищет окно в своем мэпе (а он для каждого потока разный), не находит (потому что поток не тот) и ругается.
Поэтому я, чтобы не проверять по каждому поводу - можно или нельзя, в потоках пользуюсь АПИ-функциями.
Примерно так.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)