Можно ли «раскрутить» несколько потоков GUI? (Не останавливать систему на Application.Run) - PullRequest
20 голосов
/ 06 августа 2008

Моя цель

Я хотел бы иметь основной поток обработки (без графического интерфейса пользователя) и иметь возможность при необходимости раскручивать графические интерфейсы в их собственных фоновых потоках, и чтобы мой основной поток без графического интерфейса продолжал работать. Иными словами, я хочу, чтобы мой основной не GUI-поток был владельцем GUI-потока, а не наоборот. Я не уверен, что это возможно даже с Windows Forms (?)

Фон

У меня есть система на основе компонентов, в которой контроллер динамически загружает сборки, создает и запускает классы, реализующие общий интерфейс IComponent с помощью одного метода DoStuff().

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

Срок службы всей системы выглядит следующим образом

  1. Приложение запускается.
  2. Проверьте файл конфигурации для загрузки компонентов. Загрузите их.
  3. Для каждого компонента выполните DoStuff(), чтобы инициализировать его и заставить его жить своей собственной жизнью в своих собственных потоках.
  4. Продолжайте делать главное приложение-царь работы, навсегда.

Я еще не смог успешно выполнить пункт 3, если компонент запускает графический интерфейс в DoStuff(). Он просто останавливается, пока графический интерфейс не будет закрыт. И только после закрытия графического интерфейса программа переходит к пункту 4.

Было бы замечательно, если бы этим компонентам было разрешено запускать свои собственные графические интерфейсы Windows Forms.

Проблема

Когда компонент пытается запустить графический интерфейс в DoStuff() (точная строка кода - это когда компонент запускает Application.Run(theForm)), компонент и, следовательно, наша система "зависают" в строке Application.Run() до графического интерфейса закрыто. Хорошо, только что запущенный графический интерфейс работает нормально, как и ожидалось.

Пример комплектующих. Один не имеет ничего общего с графическим интерфейсом, а второй открывает милые окна с розовыми пушистыми кроликами в них.

public class MyComponent1: IComponent
{
    public string DoStuff(...) { // write something to the database  }
}

public class MyComponent2: IComponent
{
    public void DoStuff()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form());

        // I want the thread to immediately return after the GUI 
        // is fired up, so that my main thread can continue to work.
    }
}

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

public void DoStuff()
{
    new Thread(ThreadedInitialize).Start()
}

private void ThreadedInitialize()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form());
}

Можно ли раскрутить графический интерфейс и вернуться после Application.Run()?

Ответы [ 3 ]

11 голосов
/ 06 августа 2008

Метод Application.Run отображает одну (или несколько) форм и запускает стандартный цикл обработки сообщений, который выполняется до тех пор, пока все формы не будут закрыты. Вы не можете форсировать возврат из этого метода, кроме как закрытием всех форм или принудительным закрытием приложения.

Однако вы можете передать ApplicationContext (вместо новой формы ()) в метод Application.Run, а ApplicationContext можно использовать для запуска нескольких форм одновременно. Ваша заявка закончится только тогда, когда все они закрыты. Смотрите здесь: http://msdn.microsoft.com/en-us/library/system.windows.forms.application.run.aspx

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

0 голосов
/ 24 мая 2009

Я не уверен, что это правильно, однако я помню, как запускал оконные формы из консольного приложения, просто обновляя форму и вызывая для нее newForm.Show (), если ваши компоненты используют это вместо Application.Run () тогда новая форма не должна блокироваться.

Конечно, компонент будет нести ответственность за поддержание ссылки на формы, которые он создает

0 голосов
/ 06 августа 2008

Я уверен, что это возможно, если взломать его достаточно сложно, но я бы посоветовал, что это не очень хорошая идея.

«Окна» (которые вы видите на экране) тесно связаны с процессами. То есть каждый процесс, отображающий любой графический интерфейс, должен иметь цикл сообщений, который обрабатывает все сообщения, связанные с созданием окон и управлением ими (такие вещи, как «нажатие кнопки», «закрытие приложения», «перерисовка экрана»). и так далее.

Из-за этого более или менее предполагается, что если у вас есть какой-либо цикл обработки сообщений, он должен быть доступен в течение всего жизненного цикла вашего процесса. Например, Windows может отправить вам сообщение «Quit», и вам нужно иметь доступный цикл обработки сообщений, даже если на экране ничего нет.

Лучше всего сделать это так:

Создайте поддельную форму, которая никогда не показывается и которая является вашим «основным приложением». Запускать Звоните Application.Run и передайте в этой поддельной форме. Выполняйте свою работу в другом потоке и запускайте события в главном потоке, когда вам нужно что-то делать в Gui.

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