web-dev-qa-db-ja.com

2つのwinformウィンドウを同時に実行する

2つのC#winform(.NET 4.0)フォームがあり、それぞれが個別に実行されますが、類似した自動化タスクが継続的に実行されます。それらは別個のプロセス/ワークフローであるという点で分離されていますが、プロジェクト内で同じリソース(メソッド、データモデル、アセンブリなど)を共有するために動作する方法は十分に似ています。

両方のフォームが完成しましたが、起動時に各ウィンドウが開いて個別に実行されるようにプログラムを実行する方法がわかりません。プログラムは展開されると「常時オン」になります。

これは少し基本的に思えるかもしれませんが、私の開発経験のほとんどはWebアプリケーションでした。スレッディングなどはまだ私には少し異質です。私は調査しましたが、私が見つけた答えのほとんどはユーザーの対話と順次の使用例に関連しています-これは、2つの異なるプロセスを継続的に実行する1つのシステムであり、独立して世界と対話する必要があります。

私が見つけた可能性のある解決策は、マルチスレッド化、またはおそらく何らかの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());
    }
}
19
RJB

新しい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()));
32
Servy

2つの別個のUIスレッドで実行するために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
    }
}
9
Paul Sasik

仮定

2つの異なるプロセスを必要としない必要はありません2つの異なるフォームを保持したいため、2つのプロセスのみを使用しています。両方のフォームが終了するまでアプリケーションが実行されます。

別の解決策

Form.Closedイベントメカニズム。フォームを閉じたときに何をするかを指定できるイベントハンドラーを追加できます。例えば。 bothフォームが閉じているときにアプリケーションを終了します。

いくつかのコードに関して

    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();
        }
    }

これは、より良いソリューションにするためにリファクタリングする必要があることに注意してください。


[〜#〜]更新[〜#〜]

Servyによって提供されたコメントにより、これは「単純なソリューションであると想定される」と改訂され、彼のソリューションはこのソリューションよりも優れていることが指摘されました。私は答えを残すようにサポートされているので、私はこの答えを使用します。この解決策に行くときに発生し始める問題にも対処します。

  • クローズイベントのキャンセル
  • あるイベントから別のイベントへの経路変更
  • Disposeを強制的に呼び出します。
  • サービーが指摘したように:メンテナンスに不向き(どのフォームが閉じているかを確認する状態)
1
bas