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会立即终止正在运行的应用程序。 (两种情况都正确地启动了一个新实例)。这种行为似乎没有记录在任何地方 - 文档中的含义是,就运行实例的终止而言,它与'End'是同义词。我错过了什么吗?
答案 0 :(得分:3)
回答这些问题的最好方法是使用Reflector查看代码本身(或微软免费调试代码,当它可用时)。
使用Reflector,您可以看到(在.NET Framework 4.0中)System.Windows.Forms.Application.Restart
查找四种不同类型的应用程序:
Assembly.GetEntryAssembly
为Nothing
的初步检查,如果是NotSupportedException
则会抛出; {/ li>
Process.GetCurrentProcess.MainModule.FileName
与ieexec.exe
位于与当前.NET Framework相同的文件夹中(特别是定义Object
的模块所在的文件夹); ApplicationDeployment.IsNetworkDeployed
是True
;和所有三个受支持的案例都会确定再次启动流程的方法,调用Application.ExitInternal
并再次启动流程。
Application.ExitInternal
关闭打开的表单,包括通过将FormClosingEventArgs.Cancel
设置为True
来检查试图中止结算的表单。如果没有表单尝试取消,表单将会关闭,并使用ThreadContext.ExitApplication
清除所有ThreadConnexts
(Disposed
或调用他们的ApplicationContext.ExitThread
)。
NB没有调用Thread.Abort
,因此线程 NOT 以任何方式显式结束。此外,Windows.Forms
ModalApplicationContext
甚至不会调用普通ThreadExit
所做的ApplicationContext
“事件”。
(请注意,Application.Restart
中的所有三个受支持的案例都忽略 Application.ExitInternal
的结果,因此如果表单确实试图中止所有发生的事情,那么任何其他表单没有机会关闭,ThreadContexts没有清理!)
重要的是,对于您的问题,它 NOT 尝试实际退出当前线程或整个应用程序(除了关闭打开的表单和线程上下文)。
但是,当您的MsgBox("restarting")
执行时,新应用程序已经启动。
您需要在致电Application.Restart
后手动退出应用程序。在“在表单中运行”的情况下(您没有显示测试此处的代码)表单是否已关闭,这是您认为当前应用程序结束的内容,或{{1 (或VB)设置意味着应用程序 退出其中一个“事件”,当发生的清理运行时,它会抛出。
换句话说,在测试之前,我预计Windows.Forms
会出现,即使此代码位于表单的MsgBox
事件中,表单首先消失,应用程序重新启动同一时间。
测试完之后,Click
试图出现,因为我听到与之对应的哔哔声,如果我发出评论,则不会发出哔哔声。所以有些东西会导致应用程序退出,即使它应该打开一个消息框,甚至在MsgBox
之外的MsgBox
中放置Finally
也不会出现在Application.Run
上}。 (注意,如果您在Restart
之后致电MsgBox
,则会看到类似的效果。)
因此Application.Exit
(或VB)设置的内容实际上会调用类似Windows.Forms
的内容,调用Win32Api Environment.Exit
并且不会考虑ExitProcess
或调用{{1 }或Finally
。
请注意,Dispose
文档暗示它不适用于控制台应用程序,但它目前工作正常(除了不立即退出,Finalize
不暗示)。
答案 1 :(得分:0)
根据我对Application.Restart()的一些相当高级的读数,这肯定会有点猜测,但我认为这是由于Restart在内部运行的方式而发生的。 / p>
我认为Restart()尝试对正在终止的进程进行尽可能多的“智能”清理,并且在可能被认为是相当简单的实现中,跟踪某些要清理的东西, “可能在它们上面调用Dispose()(如果适用),这通常是一个合理的步骤。在你的情况下,我将猜测后台线程或表单持有对某些内容的引用 - 不能说是什么 - 这会阻止代码关闭。它可能会意识到它正在一个方法中执行,并希望在杀死它之前给该方法一个完成的机会 - 等待该子/方法的完成。
我已经看到其他实例的重新启动实际上导致真的奇怪的“收集被修改”错误当没有涉及集合时。这对我来说可能是天真的,正在尝试实现的内部清理是在一个简单的列表中,但在某些情况下,清理以一种意想不到的方式修改元素,一种修改集合的方式,导致抛出异常,并中止退出/重新启动。
答案 2 :(得分:0)
我可以通过关闭并处理所有打开的窗体(正在调用的窗体除外)来重新启动应用程序。
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()