Выполнить одновременно два окна winform
У меня есть две формы С# winform (.NET 4.0), каждая из которых запускает отдельные, но похожие автоматические задачи. Отдельно в том, что они представляют собой различные процессы/рабочие процессы, но достаточно похожи на то, как они работают, чтобы совместно использовать одни и те же ресурсы (методы, модели данных, сборки и т.д.) В проекте.
Обе формы полны, но теперь я не уверен, как запустить программу, чтобы каждое окно открывалось при запуске и запускалось независимо. При развертывании программа будет "всегда включена".
Это может показаться немного базовым, но большая часть моего опыта разработки - это веб-приложения. Threading/etc все еще немного чуждо мне. Я исследовал, но большинство ответов, которые я нашел, связаны с взаимодействием с пользователем и последовательными вариантами использования - это будет только одна система, непрерывно выполняющая два разных процесса, которые должны будут взаимодействовать с миром независимо.
Потенциальные решения, которые я нашел, могут включать многопоточность или, может быть, какой-то MDI, или несколько людей предложили DockPanelSuite (хотя, находясь в супер-корпоративной среде, загрузка сторонних файлов проще сказать, чем сделать).
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Rather than specifying frmOne or frmTwo,
// load both winforms and keep them running.
Application.Run(new frmOne());
}
}
Ответы
Ответ 1
Вы можете создать новый ApplicationContext
для представления нескольких форм:
public class MultiFormContext : ApplicationContext
{
private int openForms;
public MultiFormContext(params Form[] forms)
{
openForms = forms.Length;
foreach (var form in forms)
{
form.FormClosed += (s, args) =>
{
//When we have closed the last of the "starting" forms,
//end the program.
if (Interlocked.Decrement(ref openForms) == 0)
ExitThread();
};
form.Show();
}
}
}
Используя это, вы теперь можете написать:
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MultiFormContext(new Form1(), new Form2()));
Ответ 2
Если вам действительно нужно два окна/формы для запуска на двух отдельных потоках пользовательского интерфейса, вы можете сделать что-то вроде этого:
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var thread = new Thread(ThreadStart);
// allow UI with ApartmentState.STA though [STAThread] above should give that to you
thread.TrySetApartmentState(ApartmentState.STA);
thread.Start();
Application.Run(new frmOne());
}
private static void ThreadStart()
{
Application.Run(new frmTwo()); // <-- other form started on its own UI thread
}
}
Ответ 3
Предположение
Вам не нужны два разных процесса, вы используете только два процесса, потому что хотите иметь две разные формы и хотите, чтобы приложение работало до тех пор, пока обе формы не будут завершены.
Другое решение
Полагайтесь на механизм событий Form.Closed
. Вы можете добавить обработчик событий, который позволяет вам указать, что делать, когда форма закрывается. Например. выйдите из приложения, когда формы обеих закрыты.
В терминах некоторого кода
public Form1()
{
InitializeComponent();
_form2 = new Form2();
_form2.Show(this);
this.Closed += Form1Closed;
_form2.Closed += Form2Closed;
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
e.Cancel = true;
Hide();
Form1Closed(this, new EventArgs());
base.OnFormClosing(e);
}
private void Form1Closed(object sender, EventArgs eventArgs)
{
form1IsClosed = true;
TryExitApplication();
}
private void Form2Closed(object sender, EventArgs eventArgs)
{
_form2IsClosed = true;
TryExitApplication();
}
private void TryExitApplication()
{
if (form1IsClosed && _form2IsClosed)
{
Dispose();
Application.Exit();
}
}
Обратите внимание, что это нужно реорганизовать, чтобы сделать его лучшим решением.
UPDATE
Комментарии, предоставленные Servy, сделали мой пересмотр этого "предполагаемого простого решения", в котором указывалось, что его решение намного лучше, чем это решение. Поскольку я поддерживаю, чтобы оставить ответ, я воспользуюсь этим ответом. Я также рассмотрю проблемы, возникающие при решении этого вопроса:
- отмена закрытия событий
- перенаправление из одного события в другое
- принудительное вызов
Dispose
.
- поскольку Servy указал: обслуживание недружественное (состояние для проверки, какая форма закрыта)