8

ここで何が起こっているのですか?この VB コードでは:

Module Module1
Sub Main()


    If MsgBox("Restart?", MsgBoxStyle.OkCancel) = MsgBoxResult.Ok Then
        Application.Restart()

        MsgBox("restarting")

    Else
        MsgBox("Cancel")

    End If

End Sub
End Module

このコードがモジュール内に含まれている場合、Application.Restart は、End Sub がヒットするまで実行中のアプリケーションを終了しません。それ以前に表示されたコードはすべて実行されます。たとえば、「再起動中」メッセージボックスが表示されます。ただし、同等のコードがフォーム内で実行されると、Application.Restart は実行中のアプリケーションをすぐに終了します。(どちらの場合も、新しいインスタンスを正しく開始します)。この動作はどこにも文書化されていないようです - ドキュメントの意味は、実行中のインスタンスの終了に関する限り、「終了」と同義であるということです。何か不足していますか?

4

3 に答える 3

4

これらの質問に答える最善の方法は、Reflector (または Microsoft の無料のデバッグ コードが利用可能な場合) を使用してコード自体を調べることです。

Reflector を使用すると、(.NET Framework 4.0 では)System.Windows.Forms.Application.Restart次の 4 種類のアプリケーションが検索されることがわかります。

  • Assembly.GetEntryAssemblyである場合Nothingの最初のチェックNotSupportedException
  • これProcess.GetCurrentProcess.MainModule.FileNameieexec.exe、現在の .NET Framework と同じフォルダー (具体的には、モジュール定義Objectがあるフォルダー) にあります。
  • ApplicationDeployment.IsNetworkDeployedですTrue。と
  • 一般的な場合。

サポートされている 3 つのケースはすべて、プロセスを再起動する方法を決定し、プロセスを呼び出しApplication.ExitInternalて再起動します。

Application.ExitInternalFormClosingEventArgs.Cancelに設定して閉じることを中止しようとするフォームのチェックを含め、開いているフォームを閉じますTrue。キャンセルしようとするフォームがない場合、フォームは閉じられ、 を使用してThreadContext.ExitApplicationすべてThreadConnextsがクリーンアップされます (DisposedまたはそれらApplicationContext.ExitThreadが呼び出されます)。

NB NoThread.Abortが呼び出されるため、スレッドは明示的に終了しません。また、は通常の「イベント」をWindows.Forms ModalApplicationContext呼び出すことさえしません。ThreadExitApplicationContext

( でサポートされている 3 つのケースはすべての結果をApplication.Restart 無視Application.ExitInternalすることに注意してください。そのため、フォームが中止を試みた場合、他のフォームは閉じる機会がなく、ThreadContext はクリーンアップされません!)

あなたの質問にとって重要なのは、現在のスレッドまたはアプリケーション全体を実際に終了しようとしないことです(開いているフォームとスレッドコンテキストを閉じることを除く)。

ただし、MsgBox("restarting")実行するまでに、新しいアプリケーションが開始されています。

を呼び出した後、アプリケーションを手動で終了する必要がありますApplication.Restart。「フォーム内で実行する」場合(これをテストしたコードは表示されません)、フォームが閉じられ、それが現在のアプリケーションの終了と見なされるか、または余分なものWindows.Forms(またはVB ) セットアップとは、発生するクリーンアップが実行されたときにスローされる「イベント」の 1 つによってアプリケーションが終了されることを意味します。

MsgBoxつまり、テストする前に、このコードがClickフォームのイベントである場合でも、最初にフォームが消え、同時にアプリケーションが再起動することを期待していました。

テストしたところ、MsgBoxそれに対応するビープ音が聞こえ、コメントアウトするとビープ音は発生しません。そのため、メッセージ ボックスが開いている必要がある場合でも、何らかの理由でアプリケーションが終了し、MsgBoxを のFinally外側に配置してもApplication.Run、 に表示されませんRestartMsgBox( の後に呼び出すと、同様の効果が見られることに注意してくださいApplication.Exit。)

Windows.Formsしたがって、 (または VB)によってセットアップされたものは、実際にEnvironment.Exitは Win32Api を呼び出し、 orを考慮したり呼び出したりExitProcessしないようなものを呼び出します。FinallyDisposeFinalize

ドキュメントは、現在正常に動作していますが、コンソールアプリケーション用ではないことを暗示していることに注意してくださいApplication.Restart(ただし、すぐに終了しないことを除きます。これは、によって暗示されていませんApplication.Exit)。

于 2012-09-23T10:50:26.160 に答える
0

確かに、これは、Application.Restart()について行ったかなりトップレベルの読み取りに基づいて少し推測されますが、これは、Restartが内部で動作する方法が原因で発生していると思います。

Reset()は、終了するプロセスに対して可能な限り多くの「インテリジェントな」クリーンアップを実行しようとし、かなり単純な実装と見なされる可能性があるもので、「クリーンアップ」される特定のものを追跡し、場合によってはそれらにDispose()(該当する場合)。これは通常、実行するのに妥当な手順です。あなたの場合、バックグラウンドスレッドまたはフォームが、コードのシャットダウンを妨げる何かへの参照を保持していると推測します。メソッド内で実行されていることに気づき、そのメソッドを強制終了する前に、そのメソッドを完了する機会を与えたい場合があります。つまり、そのサブ/メソッドの完了を待機します。

再起動の他のインスタンスが、コレクションが含まれていないときに実際に非常に奇妙な「コレクションが変更されました」エラーを引き起こすのを見てきましたこれは、おそらく単純に、Restartが達成しようとしている内部クリーンアップが単純なリストに再配置されていることを示唆していますが、特定の状況では、クリーンアップが予期しない方法で要素を変更します。これは、コレクションを変更する方法で、例外を引き起こします。スローされ、終了/再起動を中止します。

于 2012-09-21T18:34:50.977 に答える