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

StackOverflow https://stackoverflow.com/questions/2872

  •  08-06-2019
  •  | 
  •  

Вопрос

Моя цель

Я хотел бы иметь основной поток обработки (не графический интерфейс пользователя) и иметь возможность по мере необходимости выделять графические интерфейсы пользователя в их собственных фоновых потоках, а мой основной поток без графического интерфейса продолжает работать.Другими словами, я хочу, чтобы мой основной поток, не являющийся графическим интерфейсом, был владельцем потока графического интерфейса, а не наоборот.Я не уверен, что это возможно даже с 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()?

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top