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查找四种不同类型的应用程序:

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

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

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

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

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

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

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

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

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

测试后,MsgBox尝试出现,因为我听到对应的哔哔声,如果我将其注释掉,哔哔声不会发生。因此,即使应用程序应该打开一个消息框,某些东西也会导致应用程序退出,甚至将 aMsgBox放在 aFinally之外Application.Run也不会出现在 a 上RestartMsgBox(请注意,如果您在 之后调用,也会看到类似的效果Application.Exit。)

因此,由(或 VB)设置的Windows.Forms东西实际上确实调用了类似Environment.Exit调用 Win32ApiExitProcess并且不考虑Finally或调用Disposeor的东西Finalize

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

于 2012-09-23T10:50:26.160 回答
1

我可以通过关闭和处理所有打开的表单来重新启动应用程序,除了正在调用的表单。

    For j As Integer = Application.OpenForms.Count - 1 To 0 Step -1
        Dim frm = Application.OpenForms(j)
        If frm.Text <> callingForm.Text Then
            frm.Close()
            frm.Dispose()
        End If
    Next

    Application.Restart()
于 2020-04-27T16:33:27.930 回答
0

诚然,根据我对 Application.Restart() 所做的一些相当顶级的阅读,这将是一个猜测,但我认为这是由于 Restart 内部操作的方式而发生的。

我认为 Restart() 尝试对正在终止的进程进行尽可能多的“智能”清理,并且在可能被认为是相当简单的实现中,跟踪某些要“清理”的事物,可能调用Dispose() 对它们(如果适用),这通常是一个合理的步骤。在您的情况下,我将猜测后台线程或表单持有对某些东西的引用 - 不能说是什么 - 这会阻止代码关闭。它可能会意识到它正在一个方法内执行,并希望在杀死它之前给该方法一个完成的机会 - 等待该子/方法的完成。

我见过 Restart 的其他实例在不涉及收集时实际上导致了一个非常奇怪的“Collection was Modified”错误。这可能是天真地向我暗示,Restart 试图实现的内部清理被放置在一个简单的列表中,但在某些情况下,清理以一种意想不到的方式修改了元素,一种修改集合的方式,导致异常被抛出,并中止退出/重新启动。

于 2012-09-21T18:34:50.977 回答