21

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

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

これは少し基本的なことのように思えるかもしれませんが、私の開発経験のほとんどはWebアプリケーションです。糸脱毛/etcはまだ私には少し異質です。私は調査しましたが、私が見つけた答えのほとんどは、ユーザーとの対話と順次のユースケースに関連しています。これは、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());
    }
}
4

3 に答える 3

42

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()));
于 2013-03-08T18:45:30.773 に答える
10

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
    }
}
于 2013-03-08T18:44:37.897 に答える
1

予測

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

別の解決策

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

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


アップデート

Servyから提供されたコメントにより、これは「単純な解決策であると思われる」改訂になり、彼の解決策はこの解決策よりもはるかに優れていることが指摘されました。私は答えを残すことがサポートされているので、この答えを使用します。また、この解決策に進むときに発生し始める問題にも対処します。

  • クローズイベントのキャンセル
  • あるイベントから別のイベントへの再ルーティング
  • 強制呼び出しDispose
  • Servyが指摘したように:メンテナンスは不親切です(どのフォームが閉じているかを確認するための状態)
于 2013-03-08T19:09:04.933 に答える