Моя цель
Я хотел бы иметь основной поток обработки (non GUI) и иметь возможность откручивать графические интерфейсы в своих собственных потоках фона по мере необходимости, и мой основной поток без GUI будет работать. Иными словами, я хочу, чтобы мой основной non GUI-поток был владельцем GUI-потока, а не наоборот. Я не уверен, что это возможно даже с Windows Forms (?)
Фон
У меня есть компонентная система, в которой контроллер динамически загружает сборки и создает экземпляры и запускает классы, реализующие общий интерфейс IComponent
с помощью одного метода DoStuff()
.
Какие компоненты, которые загружаются, настраиваются с помощью файла конфигурации xml и путем добавления новых сборок, содержащих различные реализации IComponent
. Компоненты предоставляют служебные функции для основного приложения. В то время как основная программа делает это, например, контролируя ядерную установку, компоненты могут выполнять служебные задачи (в их собственных потоках), например. очистка базы данных, отправка писем, печать смешных шуток на принтере, что у вас есть. Я хотел бы, чтобы один из этих компонентов мог отображать графический интерфейс пользователя, например. со статусной информацией для указанного компонента отправки электронной почты.
Время жизни всей системы выглядит следующим образом:
- Запускается приложение.
- Проверить конфигурационный файл для загрузки компонентов. Загрузите их.
- Для каждого компонента запустите
DoStuff()
, чтобы инициализировать его и заставить его жить своей жизнью в своих потоках. - Продолжайте делать главное приложение - вечный король работы, навсегда.
Я еще не смог успешно выполнить точку 3, если компонент запускает графический интерфейс в DoStuff()
. Он просто останавливается, пока графический интерфейс не будет закрыт. И только после закрытия графического интерфейса программа переходит к пункту 4.
Было бы здорово, если бы этим компонентам было разрешено запускать собственные графические интерфейсы Windows Forms.
Проблема
Когда компонент пытается запустить GUI в 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.
}
}
Я пробовал это без везения. Даже когда я пытаюсь запустить GUI в своем потоке, выполнение останавливается, пока GUI не будет закрыт.
public void DoStuff()
{
new Thread(ThreadedInitialize).Start()
}
private void ThreadedInitialize()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form());
}
Можно ли отключить графический интерфейс и вернуться после Application.Run()
?