2012-11-10 260 views
6

我玩了一些C#Winforms/WPF代碼,只是偶然發現了一些奇怪的東西。 比方說,我有這樣的代碼:停止執行C#代碼

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DoSomething(); 

     // maybe something more if everything went ok 
    } 
} 

令我百思不解的是,我不能簡單地從方法DoSomething的關閉應用程序的構造函數完成其工作之前。如果在DoSomething的執行過程中出現任何問題,我需要立即關閉應用程序,但它只是繼續運行,執行// maybe something more...部分,然後關閉,但對我來說太遲了。

我必須把關閉窗體的代碼放在構造函數本身的內部,然後使用return;然後才能工作,但我並沒有真正找到可以接受的解決方案。我試圖將這種驗證邏輯從構造函數移動到我的方法中。

我試過的東西

public void DoSomething() 
{ 
    Close(); 
} 

public void DoSomething() 
{ 
    Application.Current.Shutdown(); 
} 

但它似乎並沒有工作。是的,兩個代碼都會關閉應用程序,但只能在完成完成的構造函數代碼之後。

Why我需要這樣的東西嗎?那麼,因爲在啓動時我需要檢查各種事情,比如連接和硬件的可用性,驗證用戶等,如果有任何失敗,就沒有必要執行更多的代碼。

與Winforms和WPF(因此標籤)嘗試相同的原則,工作原理相同。

任何人都可以提供解釋或解決方案嗎?我知道這可能對你們中的一些人非常基本,但是請和我一起裸露,我主要不是Windows程序員,所以這對我來說有點新意。網站的工作有點不同...... :)

+0

當創建第一種形式沒有應用程序正在運行,所以關機()可能是忽略不計。 Avip提供了很好的解決方案 –

回答

8

只要在你的情況下嘗試使用Environment.Exit(-1),一切都會很好。

添加:這是我可以爲你得到的最佳參考。

差異Application.Exit vs Application.Shutdown vs Environment.Exit

之間

Application.Exit()是一個優雅的方式退出Windows窗體應用程序。基本上,它會在Application.Run()的調用之後停止消息泵,關閉所有窗口並將其返回到Main()方法中。但是,有時它看起來不起作用 - 這通常是因爲還有其他前景線程(除了UI線程)仍在運行,這阻止線程結束。

Application.Shutdown()(大體上)等同於Application.Exit()在WPF應用程序中。但是,您可以設置更多的控件,因爲您可以設置ShutDownMode,以便在主窗口關閉,最後一個窗口關閉或僅在調用此方法時關閉應用程序。

Environment.Exit()殺死所有正在運行的線程,並且進程本身死亡。這應該只用於WF或WPF作爲最後的手段,當更優雅的方法由於某種原因不工作。它也可以用來從控制檯應用程序中突然退出。

另一個參考:How to properly exit a C# application?

+0

謝謝,這似乎表現得如預期。你能解釋一下,爲什麼它不能用'Shutdown()'或'Close()'工作?您的解決方案有沒有陷入困境? – walther

+0

沒有陷阱。相反,Environment.Exit的核心職責是終止流程併爲底層操作系統提供指定的退出代碼。參考:http://msdn.microsoft.com/en-us/library/system.environment.exit.aspx –

+0

謝謝。有時我不需要拋出異常等,只是簡單的「退出」。 :) – walther

0

一個解決方法是拋出一個異常,並處理它在application.UnhandledException

3

你總是可以忽略你的其他開發人員和只使用Environment.FailFast()

但實際上 - 唐「T。如果你有關鍵的事情要做,S.A覈實串行端口連接到核電站,只是事先做好。只要Main()被調用,沒有規則強迫你去Application.Run(...)

+0

你能否詳細說明,爲什麼不這樣做?來自FSX的解決方案似乎有效,是否有任何潛在的問題需要了解他的方法? 'Application.Run'只與Winforms相關(或者我錯了?),但WPF呢?請問,你可以在WPF中展示一個例子來說明你的解決方案,例如你會在哪裏放置關鍵的啓動指令(檢查打開的端口和類似的東西)?簡單的例子會做。 – walther

0

定義一個異常類:

public class InitializationException : Exception 
{ 
    public InitializationException() 
    {} 

    public InitializationException(string msg) 
     : base(msg) 
    {} 

    public InitializationException(string msg, Exception inner) 
     : base(msg, inner) 
    {} 
} 

,改變你的代碼是這樣的:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     try 
     { 
      DoSomething(); 

      // maybe something more if everything went ok 
     } 
     catch(InitializationException ex) 
     { 
      // log the exception 
      Close(); 
     } 
    } 

    public void DoSomething() 
    { 
     if (notSomethingOK) 
      throw new InitializationException("Something is not OK and the applicaiton must shutdown."); 
    } 
} 

這是一個乾淨和維護的解決方案。

1

已經發布可行的解決方案爲您的問題。

只是爲了回答您的後續問題:爲什麼像關閉方法()和關斷()不會立即退出你的應用程序的原因是,這兩個剛剛推送消息到應用程序的消息隊列。只有在MainWindow的構造函數完成並且代碼執行返回到消息處理循環後,纔可以處理它們,甚至在處理了隊列中的其他仍然未決的消息之後也可以處理它們。 相反,像Environment.Exit()或Environment.FailFast()這樣的方法是一種核心os函數,可以或多或少地立即終止進程。

+0

謝謝你的解釋。恥辱我無法選擇多個答案。至少+1你也:) – walther

0
System.Windows.Forms.Application.Exit(); 
0

從概念上講,這樣的事情不應該在類的構造函數中使用。構造函數在某種程度上用於初始化初始狀態,而不是實際的事情可能發生(如異常,消息框等)。

不要忘了,你可以回報;來自構造函數,如果你需要中斷它的執行。這是更好的策略(大多數情況下,你不需要關閉錯誤的應用程序而不顯示一些文本)。

有「顯示窗口」,「可見性改變」,「裝」在C#和許多其他事件在Windows/WPF,你幾乎可以覆蓋或添加爲事件處理。在那裏初始化您的表單/應用程序。

他們是正常的方法,使所有的作品如預期。您可以嘗試拋出應用程序入口點(主函數)只會捕獲和忽略的異常。

對於WPF,看看這個: - https://msdn.microsoft.com/en-us/library/system.windows.forms.application.setunhandledexceptionmode(v=vs.110).aspx