У меня есть приложение Windows Forms (.NET), которое может одновременно открывать несколько документов.
Было бы удобно, если бы каждый документ (форма) выполнял свой собственный цикл обработки событий. После краткого экспериментирования кажется, что запуск нескольких циклов обработки событий в их собственных потоках STA работает. Есть ли причина, по которой это плохая идея?
Наше время запуска очень дорого, и мы хотели бы иметь возможность обмениваться документами без использования IPC.





Просто будьте осторожны с доступом к элементам графического интерфейса из потоков.
Немодальные формы могут быть более подходящими для ваших целей. Используйте form.Show () вместо form.ShowDialog ().
+1 действительно. Разве все так не поступают? Таким образом вы можете показать столько форм, сколько захотите.
У нас уже есть несколько окон с немодальными формами в одном потоке пользовательского интерфейса. У этого подхода есть определенные проблемы, которые мы хотели бы преодолеть (например, мы хотим, чтобы некоторые диалоги были модальными для отдельного окна, но не для всех открытых документов).
Возможно, было бы разумнее использовать контейнер MDI (многодокументный интерфейс) и дочерние формы. В этом случае каждый документ будет иметь свою собственную форму, что технически означает, что каждый документ имеет свою собственную очередь сообщений.
MDI является ИЗБЫТОЧНЫМ с точки зрения пользователя, поскольку рабочий стол является контейнером MDI.
Почему вся эта ненависть к MDI ?? Все приложения MS Office являются MDI.
Word не использует MDI. Использование MDI затрудняет использование Excel - попробуйте открыть два документа на двух разных мониторах ...
В последних двух версиях приложения Office были мульти-SDI (что означает, что они позволяют рабочему столу служить контейнером MDI). Чтобы успокоить людей, которые не переносят изменений, есть переключатель конфигурации, который снова превращает их в приложения MDI, но я никогда не видел, чтобы он использовался.
Как вы думаете, почему вам нужно более одного цикла сообщений? Один цикл сообщений может обрабатывать любое количество окон.
Если вы обнаружите, что длительная операция в одном окне может привести к зависанию всего приложения, тогда ответ состоит в том, чтобы разделить длительную работу на что-то вроде Справочная информация, оставив пользовательский интерфейс реагирующим.
Программирование с несколькими потоками, каждый со своим собственным пользовательским интерфейсом, намного сложнее, потому что один поток не может получить доступ к окнам и элементам управления, созданным из другого потока.
Модальные диалоги блокируют все приложение. Нам делать нужны они для блокировки формы (документа), из которой они вызываются, но не для блокировки всего приложения.
Я думаю, что совершенно нормально создавать несколько циклов сообщений в разных потоках. Единственное, на что следует обратить внимание, это при работе со сторонними инструментами пользовательского интерфейса, они иногда хранят дескрипторы как статические (вместо ThreadStatic) члены, и если у вас есть несколько потоков пользовательского интерфейса в вашем приложении, у него будут проблемы (в моем случае я обнаружил что ускорители клавиатуры меню / панели инструментов не работали должным образом).
Одна из главных причин для этого - наличие модальных диалоговых окон, которые отображаются в различных немодальных диалоговых окнах. Если вы поместите все в один и тот же цикл сообщений, то, если в одном из немодальных диалогов есть модальный диалог, все приложение (все окна) блокируется до тех пор, пока вы не закроете модальный диалог.
И, как говорил Кевин, остерегайтесь межоконных (перекрестных) вызовов. Вы можете использовать Control.BeginInvoke или Control.Invoke для публикации вызовов делегатов в других потоках пользовательского интерфейса.
Еще одна вещь, которую следует учитывать, - это то, как вы будете выходить из процесса. Скорее всего, вам нужно будет отслеживать циклы сообщений, чтобы вы могли остановить их, когда захотите все закрыть. Если вам все равно, и вы просто хотите, чтобы процесс завершился, когда все окна будут закрыты, вы тоже можете это сделать.
Еще одно преимущество, на которое стоит обратить внимание, - это то, что вы получаете один Application.ThreadException на цикл сообщений. Вы можете использовать это, чтобы логически «сгруппировать» вместе окна (например, все окна, принадлежащие одному логическому варианту использования / рабочему процессу), дать им выделенный поток и цикл сообщений и перехватывать необработанные исключения только из этих окон в Application.ThreadException этого потока.
Почему бы вам просто не запустить несколько экземпляров, по одному на документ?