Моя цель
Я хотел бы иметь основной поток обработки (без графического интерфейса пользователя) и иметь возможность при необходимости раскручивать графические интерфейсы в их собственных фоновых потоках, и чтобы мой основной поток без графического интерфейса продолжал работать. Иными словами, я хочу, чтобы мой основной не GUI-поток был владельцем GUI-потока, а не наоборот. Я не уверен, что это возможно даже с Windows Forms (?)
Фон
У меня есть система на основе компонентов, в которой контроллер динамически загружает сборки, создает и запускает классы, реализующие общий интерфейс IComponent
с помощью одного метода DoStuff()
.
Какие компоненты, которые загружаются, настраиваются с помощью файла конфигурации xml и путем добавления новых сборок, содержащих различные реализации IComponent
. Компоненты предоставляют служебные функции для основного приложения. В то время как основная программа делает свое дело, например, управляя ядерной установкой, компоненты могут выполнять служебные задачи (в своих потоках), например очистка базы данных, отправка электронных писем, распечатка смешных анекдотов на принтере, что там у вас. Я хотел бы, чтобы один из этих компонентов мог отображать графический интерфейс, например, с информацией о состоянии указанного компонента отправки электронной почты.
Срок службы всей системы выглядит следующим образом
- Приложение запускается.
- Проверьте файл конфигурации для загрузки компонентов. Загрузите их.
- Для каждого компонента выполните
DoStuff()
, чтобы инициализировать его и заставить его жить своей собственной жизнью в своих собственных потоках.
- Продолжайте делать главное приложение-царь работы, навсегда.
Я еще не смог успешно выполнить пункт 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()
?