brokkster Ответов: 1

Проблемы с отправкой сообщений windows в диалоговые окна, созданные в разных потоках


Я создаю пользовательскую структуру данных, которая представляет собой двоичное дерево объектов и двоичных деревьев. т. е. каждый узел в дереве верхнего уровня может быть " объектом "или" objectContainer "(который, в свою очередь, может иметь"object "или"objectContainer" для узлов).

У меня есть насос сообщений в моем основном потоке, с помощью этого насоса я обрабатываю все сообщения Windows, предназначенные для моего главного окна (щелчки, перетаскивание и изменение размера, нажатия кнопок). А когда он не работает с сообщениями Windows, он запускает таймер и обновляет сцену. Когда главное окно получает определенное нажатие клавиши, оно (в настоящее время) запускает новый поток, этот поток затем создает новый объект (или objectContainer), и во время создания нового объекта создается модальное (блокирующее) диалоговое окно, так что пользователь может взаимодействовать с / вводить начальные значения для вновь созданного объекта. После нажатия кнопки ОК, если предоставленное имя уникально (в отношении содержимого контейнера верхнего уровня), новый объект добавляется в контейнер верхнего уровня. Наконец, если модальное диалоговое окно (порожденное изнутри еще одного потока), которое отображает содержимое контейнера (в данном случае верхнего уровня), открыто, я отправляю сообщение WM_message в указанное диалоговое окно, которое предназначено для того, чтобы сообщить ему добавить имя нового элемента в список строк. У меня проблемы с отправкой этих сообщений в диалоговые окна. Например, когда я создаю objectContainer, правильное имя появляется в списке сразу после нажатия кнопки OK, но не в том случае, если я создаю объект. Я предположил, что это может иметь какое-то отношение к потокам, но я не знаю. Каждый тип объекта использует одну и ту же функцию addObject (), в которой поле отображения контейнера проверяется на предмет того, открыто оно или нет, и отправляется сообщение.

Что я уже пробовал:

Я читал статьи, в которых говорится, что никогда не используйте резьбу... если только вам это абсолютно не нужно! И что весь пользовательский интерфейс должен быть сделан в одном потоке. Некоторые даже говорят, что нужно делать UI только через основной поток. Я попробовал варианты своего применения с некоторыми методами, которые, как мне кажется, предлагают авторы этих статей, но что-то не так.

Я сделал версию, в которой при нажатии кнопки основной поток порождает немодальный диалог, который выполняет работу по взаимодействию с вновь созданным объектом. Это работает хорошо, за исключением того, что, скажем, пользователь перетаскивает немодальное диалоговое окно в течение длительного периода времени, основной процесс останавливается. У меня есть функция после части IsDialogMessage основного насоса сообщений, которая вычисляет частоту кадров и запускается, когда пользователь щелкает и удерживает немодальное диалоговое окно. Я не думаю, что хочу, чтобы это произошло, функции, обновляющие сцену, не запускаются, пока пользователь не отпустит. (если подумать, если я перетаскиваю главное окно, обработка частоты кадров тоже останавливается ... но я подозреваю, что это неизбежно, верно? если только эта обработка не выполняется в отдельном потоке ...?)

Я также создал версию, в которой после нажатия кнопки основной поток запускает новый поток, новый поток создает новый объект или objectContainer и сразу после создания нового элемента порождает немодальное диалоговое окно для editObject (). В немодальном диалоговом окне вызывающий поток не блокируется, поэтому я добавил насос сообщений сразу после создания указанного немодального диалогового окна, и он, похоже, работает. Я еще не тестировал добавление объектов и проверку уникальности имени в контейнере верхнего уровня. Я не знаю, дойдет ли wm_messages до нужного окна и будет ли управлять списком строк диалогового окна, как я хочу.

У меня возникают проблемы с каждой из моих попыток проектирования, и я просто хотел бы знать ваши мысли о дизайне, прежде чем тратить больше времени на отладку плохого дизайна. Должен ли основной поток откручиваться от потока и вызывать модальное диалоговое окно? Или все диалоговые окна должны вызываться из основного потока, и я каким-то образом перемещаю то, что, по моему мнению, должно постоянно обрабатываться, в свой собственный поток? Или основной поток должен отделиться от потока, а затем использовать немодальные диалоговые окна?

Richard MacCutchan

Если вы решили использовать потоки, то вам нужно добавить механизм синхронизации событий при создании ваших объектов. Если поток а порождает поток в, то они запускаются независимо, но нет никакой гарантии, какой из них выполнит какую-либо из своих задач первым. Читайте об использовании семафоров для синхронизации задач.

1 Ответов

Рейтинг:
9

Randor

Привет,

Я не слышал об этой проблеме уже почти десять лет. :)

Я бы рекомендовал вам сохранить все "создание окон" и "управление окнами" в главном потоке. Модальные окна могут пожирать ваши сообщения потока.

Спасение сообщений потока из модальных циклов с помощью фильтров сообщений[^]

Сообщения потока съедаются модальными циклами[^]

Вы действительно смотрите на плохой дизайн программного обеспечения... будьте осторожны, потому что некоторые из этих ошибок поедания сообщений происходят менее чем в 1% случаев... если это коммерческое программное обеспечение, у вас могут быть сотни клиентов, жалующихся на ошибки, пока вы сидите в своем офисе и говорите: -Это работает на меня!"

Избегайте запуска модального диалога из рабочего потока, если вы ожидаете, что поток сможет получать сообщения потока. Вместо этого ... попросите ваши рабочие потоки, не связанные с графическим интерфейсом, отправить сообщение обратно в основной поток и разрешить этому потоку создавать/управлять всеми окнами.

с наилучшими пожеланиями,
- Дэвид Делон


brokkster

весьма интересный. сообщение, поедающее Жуков ... ужасно.
и я предполагаю, что немодальные коробки, порожденные рабочими потоками, тоже не являются стартером? (конечно, это так; держите пользовательский интерфейс в основном потоке.)
я отстал на десять лет? может быть, я смогу взять урок.
потоковые сообщения... я использую SendMessage, а не PostMessage(если это вообще имеет значение на данный момент), я предполагаю, что если рабочие потоки общаются обратно с основным потоком, то это должен быть PostMessage, не так ли?
спасибо за помощь.
-Скотт

Randor

Да, вы отстали более чем на десять лет. Похоже, вы достигли той точки в развитии Win32, когда у вас достаточно знаний, чтобы попасть в беду.

Прочтите все это:

https://msdn.microsoft.com/en-us/library/ms810439.aspx

(Обратите внимание на дату 1993 года)

Прокрутите вниз до этих частей:
Как Несколько Потоков Влияют На Управление Окнами
Влияние нескольких потоков на маршрутизацию сообщений

Есть некоторые вещи, которые не упоминаются в этом документе...

Когда вы делаете это из рабочего потока:

mainThread- & gt;DoSomething();

Угадайте, куда идут все оконные сообщения для вашего рабочего потока? К вашему основному потоку на время вызова.

Никогда не переходите через потоки для выполнения кода из рабочих потоков графического интерфейса.

Соблюдать следующие правила:
1.) Создавайте окна и управляйте ими только из основного потока.
2.) Никогда не достигайте через потоки GUI для выполнения кода: somethread - > DoSomething (); вместо этого отправьте сообщение в свой поток, инструктируя его DoSomething();

brokkster

спасибо.