System.Windows.Forms 名前空間の Application.Exit() は、MSDNに記載してあるとおり、開いているフォームのいずれかの FormClosing イベントでクローズをキャンセル(FormClosingEventArgs.Cancel = true)した場合、アプリケーションは終了されない。
Application.Restart() に至っては、キャンセル時は、アプリケーションは終了されず、新たなアプリケーションが立ち上がる。まあ、MSDNに「主に ClickOnceアプリで使え」とあるので、Formアプリはあまり考慮されてないのかもしれない・・・。
※Application.Restart() の処理内容は簡単で、Formアプリの場合は Application.Exit() と同じ処理をした後、Process.Start()で自身の exe を起動するだけである。起動時のパラメーターも元のプロセスと同じ内容が使用される。(ClickOnceアプリや URL クリックで起動したアプリの場合は少々異なる。)
この場合に、Application.Exit()/Restart() を使うと、終了しなかったり、アプリケーションが2つ立ち上がったりする。
下記では、ユーザーによるUI操作で閉じられる場合のみ、キャンセルするようにしている。
そうすれば、Application.Exit()/Restart() の問題は起こらなくなる。(ユーザーのUI操作で、イベント内に記述したApplication.Exit()/Restart()が呼ばれても、CloseReason は UserClosing にはならない。)
他の解決手段として、Application.Exit()/Restart() を自分で実装することもできる。
※Application.OpenForms すべてに対して、Close() -> Dispose() するなど。
※再起動処理の挙動は、キャンセル無視の強制終了で新プロセス起動、または、キャンセル時は二重起動せず例外発生、など。
Application.Restart() に至っては、キャンセル時は、アプリケーションは終了されず、新たなアプリケーションが立ち上がる。まあ、MSDNに「主に ClickOnceアプリで使え」とあるので、Formアプリはあまり考慮されてないのかもしれない・・・。
※Application.Restart() の処理内容は簡単で、Formアプリの場合は Application.Exit() と同じ処理をした後、Process.Start()で自身の exe を起動するだけである。起動時のパラメーターも元のプロセスと同じ内容が使用される。(ClickOnceアプリや URL クリックで起動したアプリの場合は少々異なる。)
問題となるケース
フォームクローズをキャンセルする例として、下記のようにモードレスウィンドウの閉じる処理を、Hide() で行う場合がある。この場合に、Application.Exit()/Restart() を使うと、終了しなかったり、アプリケーションが2つ立ち上がったりする。
public class ModelessForm : Form
{
protected override void OnFormClosing(FormClosingEventArgs e)
{
e.Cancel = true;
Hide();
base.OnFormClosing(e);
}
// 以下省略
}
解決手段
おそらく、最も簡単で合理的な解決手段は、FormClosingEventArgs.CloseReason でクローズ理由を判定することである。下記では、ユーザーによるUI操作で閉じられる場合のみ、キャンセルするようにしている。
そうすれば、Application.Exit()/Restart() の問題は起こらなくなる。(ユーザーのUI操作で、イベント内に記述したApplication.Exit()/Restart()が呼ばれても、CloseReason は UserClosing にはならない。)
public class ModelessForm : Form
{
protected override void OnFormClosing(FormClosingEventArgs e)
{
if( e.CloseReason == CloseReason.UserClosing ){
e.Cancel = true;
Hide();
}
base.OnFormClosing(e);
}
// 以下省略
}
他の解決手段として、Application.Exit()/Restart() を自分で実装することもできる。
※Application.OpenForms すべてに対して、Close() -> Dispose() するなど。
※再起動処理の挙動は、キャンセル無視の強制終了で新プロセス起動、または、キャンセル時は二重起動せず例外発生、など。
0 件のコメント:
コメントを投稿