VB には BASIC の時代から連綿と語り継がれている命令がありまして、End 命令もその一つ。しかしこの End 命令を安易に使うとひどい目にあう場合があります。
たとえば最近の言語では例外機構が装備されていて、Finally ブロックは必ず実行すると信じられています。しかし、End 命令を使用すると Finally ブロックは実行されません。
Module Module1 Sub Main() Try Console.WriteLine("終了") End Finally Console.WriteLine("ここは通らない") End Try End Sub End Module
End 命令は .net 的には Environment.Exit(0) で、C言語でいう exit(0); と等価です。プログラムがその場で中断されてしまいます。なのでパッと見た目正常にプロセスが落ちたように見えますが、いろいろな処理が抜け落ちてしまっている可能性があります。
特に「Finally で後処理をしているから大丈夫」という前提を持つとき、誰かが End を使用すると、その前提が覆ってしまいます。つまり、Finally への信頼が裏切られてしまいます。
また同様に、GUI 系では、プロセス(?)の終了イベントとして、MyApplication_Shutdown (WinForms) や Application_Exit (WPF) が用意されていますが、End を使用するとこのイベントが発生しません。この点も注意すべきポイントです。
したがって、End 命令は安易に使うべきではありません。特に、プロセスが終了しないから End で終了させよう、というアプローチを行うと、後日死ぬ目を見ることがあるので注意です。
ちなみに以下は End (Environment.Exit) を実行したときに通る箇所と通らない個所のまとめ。
Finalizer は実行されますが、Dispose メソッドや Finally ブロックは実行されず、Thread も唐突に閉じられます。
Module Module1 Sub Main() ' Newのみ Dim obj = New Class1 ' ワーカースレッド起動 Dim t = New System.Threading.Thread(AddressOf worker) t.Start() Try System.Threading.Thread.Sleep(1000) Console.WriteLine("終了") Environment.Exit(0) ' End Finally Console.WriteLine("ここは通らない") End Try End Sub ' ワーカースレッド Sub worker() Try Console.WriteLine("スレッド実行中") ' 無限待ち System.Threading.Thread.Sleep(-1) Finally Console.WriteLine("ここは通らない") End Try End Sub End Module Class Class1 Implements IDisposable ' ファイナライザー Protected Overrides Sub Finalize() Console.WriteLine("ここは通る") End Sub #Region "IDisposable Support" ' IDisposable Protected Overridable Sub Dispose(disposing As Boolean) Console.WriteLine("ここは通らない") End Sub Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub #End Region End Class
[VB.NET] Application.Exit の使用は期待を裏切る | オールトの雲
[...] 「End の使用は信頼を裏切る」(http://ooltcloud.sakura.ne.jp/blog/201312/article_11223915.html)の続きエントリーです。 [...]
Link | 2013年12月19日 00:22