Application.restart-VB.Net中的令人困惑的行为

pet*_*erG 5 vb.net

好的,这是怎么回事?在此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
Run Code Online (Sandbox Code Playgroud)

如果此代码包含在模块中,则在单击End Sub之前,Application.Restart不会终止正在运行的应用程序。然后执行之前出现的所有代码-例如,出现“正在重新启动”消息框。但是,如果等效代码在表单中运行,则Application.Restart会立即终止正在运行的应用程序。(两种情况下都可以正确启动新实例)。这种行为似乎在任何地方都没有得到证明-文档中的含义是,就正在运行的实例的终止而言,它与'End'是同义词。我想念什么吗?

Mar*_*urd 5

回答这些问题的最佳方法是使用 Reflector 查看代码本身(或者 Microsoft 的免费调试代码,如果可用的话)。

使用 Reflector,您可以看到(在 .NET Framework 4.0 中)System.Windows.Forms.Application.Restart查找四种不同类型的应用程序:

  • 最初的检查Assembly.GetEntryAssemblyNothing,抛出一个NotSupportedException,如果是则
  • 与当前 .NET FrameworkProcess.GetCurrentProcess.MainModule.FileName位于ieexec.exe同一文件夹中(特别是模块定义所在的文件夹Object);
  • ApplicationDeployment.IsNetworkDeployedTrue; 和
  • 一般情况。

所有三种支持的情况都确定再次启动进程的方法,调用Application.ExitInternal并再次启动进程。

Application.ExitInternal关闭打开的表单,包括检查尝试通过设置FormClosingEventArgs.Cancel来中止关闭的表单True。如果没有表单尝试取消,则表单将关闭,并使用清除ThreadContext.ExitApplication所有表单(或调用它们)。ThreadConnextsDisposedApplicationContext.ExitThread

注意 NoThread.Abort被调用,因此线程不会以任何方式显式结束。此外Windows.Forms ModalApplicationContext, 甚至不调用ThreadExit普通函数所ApplicationContext调用的“事件”。

(请注意,所有三种受支持的情况都会Application.Restart 忽略的结果Application.ExitInternal,因此,如果一个表单确实尝试中止所有发生的情况,则任何其他表单都没有机会关闭,并且 ThreadContext 不会被清理!)

对于您的问题来说,重要的是,它不会尝试实际退出当前线程或整个应用程序(除了关闭打开的表单和线程上下文之外)。

但是,当您MsgBox("restarting")执行时,新应用程序已经启动。

调用后需要手动退出应用程序Application.Restart。在“在表单内运行[ing]”的情况下(您没有显示测试此代码的代码),要么表单已关闭,这就是您认为当前应用程序结束的内容,要么是额外的内容(或Windows.FormsVB ) 设置意味着应用程序由运行清理时引发的“事件”之一退出

换句话说,在测试它之前,我预计MsgBox即使此代码是表单Click事件,表单首先消失,应用程序同时重新启动,也会出现。

测试后,当MsgBox我听到与其相对应的蜂鸣声时,尝试出现,如果我将其注释掉,则不会出现蜂鸣声。因此,即使应用程序应该打开一个消息框,某些东西也会导致应用程序退出,甚至将 aMsgBox放在Finally的外部Application.Run也不会出现在Restart. MsgBox(请注意,如果您在 后调用,则会看到类似的效果Application.Exit。)

因此,由(或 VB)设置的东西Windows.Forms实际上会调用类似Environment.Exit调用 Win32Api 的东西ExitProcess,并且不会考虑Finally或调用DisposeFinalize

请注意,Application.Restart文档暗示它不适用于控制台应用程序,尽管它目前工作正常(除了不立即退出,这不是由 暗示的Application.Exit)。