Подтвердить что ты не робот

Выполнить одновременно два окна 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());
    }
}
4b9b3361

Ответ 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 указал: обслуживание недружественное (состояние для проверки, какая форма закрыта)