2012-09-21 66 views
4

OK傢伙令人不解的行爲,這是怎麼回事? 在這種VB代碼:Application.restart - 在VB.Net

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被擊中結束運行的應用程序。之前出現的任何代碼都會被執行 - 例如出現「Restarting」消息框。 然而,如果相當於代碼的形式內運行,那麼Application.Restart立即終止運行的應用程序。 (這兩種情況都正確啓動一個新實例)。這種行爲似乎沒有被記錄在任何地方 - 文檔中的含義是,就運行實例的終止而言,它與'結束'是同義的。我錯過了什麼嗎?

回答

3

回答這些問題的最佳方法是使用Reflector(或Microsoft的免費調試代碼,當它可用時)查看代碼本身。

隨着反射,你可以看到(在.NET Framework 4.0中)System.Windows.Forms.Application.Restart查找四種不同類型的應用:

  • 初步檢查Assembly.GetEntryAssemblyNothing,扔了NotSupportedException如果是;
  • Process.GetCurrentProcess.MainModule.FileName是在同一文件夾作爲當前的.NET Framework(具體的文件夾,其中限定Object模塊是)ieexec.exe;
  • ApplicationDeployment.IsNetworkDeployedTrue;和
  • 一般情況。

所有三個支持的情況都決定了再次啓動該過程的方法,調用Application.ExitInternal並再次啓動該過程。

Application.ExitInternal關閉打開的表單,包括通過將FormClosingEventArgs.Cancel設置爲True來嘗試中止關閉。如果沒有表單嘗試取消,則表單將被關閉,並使用ThreadContext.ExitApplication清除所有ThreadConnextsDisposed或調用它們的​​)。

NB沒有Thread.Abort被調用,所以線程是不是明確以任何方式結束。此外,Windows.FormsModalApplicationContext甚至不稱ThreadExit「事件」,即正常的ApplicationContext

(請注意,在Application.Restart所有支持的三種情況下忽略Application.ExitInternal的結果,因此,如果格式做嘗試中止所有發生的任何其他形式沒有得到一個機會接近,而ThreadContexts是沒有清理!)

重要的是你的問題,但它確實企圖實際退出當前線程或整個應用程序(不是關閉打開的形式和線程上下文)等。

但是,當您的MsgBox("restarting")執行時,新應用程序已啓動。

您需要在撥打Application.Restart後手動退出應用程序。在「在表單中運行[ing]」的情況下(您沒有在代碼中顯示您測試的代碼),表單將被關閉,這就是您認爲的當前應用程序的結尾,或者是額外的東西Windows.Forms(或VB)設置意味着應用程序退出的「事件」之一,當發生清理時發生的「事件」運行。

換句話說,在測試它之前,我預計MsgBox即使在代碼是在表格的Click事件中也會出現,並且表單首先消失,並且應用程序同時重新啓動。

經過測試,MsgBox試圖出現,因爲我聽到與它對應的嘟嘟聲,並且如果我將它註釋掉,則不會發出嘟嘟聲。因此,一些會導致應用程序甚至退出,雖然它應該有一個消息框打開,甚至把一個MsgBoxFinallyApplication.Run不會出現在Restart。 (請注意,如果您Application.Exit後調用MsgBox類似的作用見圖)。

因此就成立了由Windows.Forms(或VB)並實際調用像Environment.Exit它調用WIN32API ExitProcess,不把Finally或致電DisposeFinalize

注意Application.Restart文檔意味着它不適用於控制檯應用程序,雖然它目前工作正常(除非不立即退出,這不是暗示的Application.Exit)。

+0

感謝您的詳盡答覆馬克。 窗體版本只是Application.Restart(),然後MsgBox(「重新啓動」)在窗體上的按鈕的單擊事件中。沒有信息箱,沒有嘟嘟聲。 – peterG

+0

是的,消息嗶聲會是某種競爭條件。在某些機器上,我確定你會看到消息框出現,然後消失,沒有按下OK按鈕,因爲應用程序已經調用了ExitProcess。我尚未確認此通話設置的位置。 –

0

這是肯定的,根據我對Application.Restart()所做的一些相當頂級的閱讀,我認爲這是由於Restart在內部運行的方式而產生的猜測。我覺得Restart()試圖儘可能多地對正在被終止的進程進行「智能」清理,並且在可能被認爲是相當簡單的實現中,追蹤某些被「清理掉」的東西,「可能調用Dispose()(如果適用),這通常是一個合理的步驟。就你而言,我將猜測後臺線程或表單對某些東西(不能說什麼)持有引用,從而阻止代碼關閉。它可能會意識到它在一個方法內執行,並希望在殺死它之前有機會完成該方法 - 等待該子/方法的完成。

我見過實際上造成重啓的其它情形真正奇怪的「集合被修改」的錯誤當沒有收集參與。這是暗示我,也許天真,該內部清理重新啓動正試圖實現一個簡單的列表裏的,但在某些情況下,清理修改元素以意想不到的方式,修改該集合的方式,導致異常被拋出,並中止退出/重新啓動。

+0

謝謝你,但我真的希望得到更明確的答案。我可以通過簡單地在application.restart後面加一個'End'來讓它工作,但這仍然讓我感到有點不安,尤其是因爲這是我銷售的應用程序中的代碼(代碼示例I發佈是一個骨架,仍然表現出奇怪的行爲 - 生產代碼是有點複雜。) – peterG