WPF 退出程序


C#如何優雅的退出應用程序

 

前言

I should know how I am supposed to exit my application when the user clicks on the Exit menu item from the File menu. 或者點擊window右上角的X退出應用。

但是退出應用程序時,應該考慮到哪些點呢?

(1)有人認為在關閉應用前,應該觸發一個確認窗口,指示用戶是否確認退出,因為if there are jobs running, the force exit will cause damages, so we better to let them informed in the confirmation dialog。

(2)有人認為太多的確認是一件非常糟糕的事情。事實上,有人花了點擊打開文件菜單,一直向下移動到文件菜單的底部,然后單擊退出,幾乎確認他們不再希望使用該應用程序。

其實就我來看,上面兩類觀點都有道理,關鍵是要適合自己的情況。(This is better to be designed case by case,此話老套而不過時)

如何根據實際情況進行權衡,就是本文要討論的如何優雅地退出應用程序的問題,只不過這里只針對WPF應用而言。

 

正文

作為一個程序員,我們先關注下實現exit application的技術。

  • 首先,我們可能想到使用:
Application.Current.Shutdown();

(注:Application.Current.Shutdown(); 只能從創建Application對象的線程調用,即通常是主線程)

我做過測試,在MainWindow中,我觸發了其他幾個windows,然后在MainWindow的window_closed事件中,我添加了該代碼,所有的窗口都消失了,但后台程序仍舊在運行。

這是為什么呢?

其實,所有其他owned窗口會被關閉,但你必須確保聲明所有權。如果你有一個正在運行的窗口,然后打開另一個窗口但尚未顯示,則在關閉活動窗口后,隱藏的窗口將強制應用程序繼續運行。除非你通過其他方式(任務管理器等)關閉該窗口,否則將會有潛在的內存泄漏。

另外值得注意的是:Application.Current.Shutdown();是不可逆轉的,它通常用於強制應用程序關閉,例如用戶注銷或關閉Windows時。Instead, 在主窗口中調用this.close(), 這與按“ALT-F4”或窗口上的關閉[x]按鈕作用相同。這將導致所有其他所有的窗口關閉,並將最終調用Application.Current.Shutdown();只要關閉動作未被取消。可參閱關閉窗口的MSDN文檔。

另外,由於this.close()可以取消,你可以在關閉事件處理程序中放入保存更改確認對話框。只需要構建<Window Closing =“...”>的事件處理程序,並相應地更改e.Cancel的值(true or false)。

 

  • 其次,如果你真的需要關閉應用程序,你也可以使用Environment.Exit(),但它並不優雅(更像是結束進程):
Environment.Exit(0)

Environment.Exit()至少需要一個參數,一個退出代碼。如果你不關心退出代碼,就像上面那么用。

Environment.Exit is definitely the right way to ensure shutdown of an application. With Application.Current.Shutdown you can easily end up with the application running on indefinitely if you have code that pushes itself back into the dispatcher. 意思就是說這絕對是確保關閉應用的正確方式。使用Application.Current.Shutdown,當你的代碼中有回調自身的情況時,很容易出現程序無限運行的結果。

注:與Application.exit(0);同等效果。

 

 

代碼實例:

MainWindow.xaml中windows部分詳情如下:

1
2
3
4
5
6
7
8
9
<Window
         xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x= "http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d= "http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc= "http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local= "clr-namespace:Application"       
         mc:Ignorable= "d"
         
         Title= "Application"  Height= "1050"  Width= "1800"  Closing= "Window_Closing"  Icon= "Images/app_icon.png"  Loaded= "Window_Loaded" >

 MainWindow.xaml.cs關鍵部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// Any control that causes the Window.Closing even to trigger.
private  void  MenuItem_Exit_Click( object  sender, RoutedEventArgs e)
{
     this .Close();
}
 
// Method to handle the Window.Closing event.
private  void  Window_Closing( object  sender, System.ComponentModel.CancelEventArgs e)
{
     try
    {
         MessageBoxResult msgBoxResult = MessageBox.Show( "Do you really want to exit?" "Exiting..." , MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
 
         if  (msgBoxResult == MessageBoxResult.No)
         {
             e.Cancel =  true ;
             return ;
         }
         else
         {
             var  jobState = XXX.GetJobState();
             if  (jobState == finished || ...)
             {
                 e.Cancel =  false ;
             }
             else
            {
                 MessageBox.Show( "Application is running job, please wait till finish. " );
                 e.Cancel =  true ;
                 return ;
             }
         }
 
         //to do something Uninitialize or ...
             
     }
     catch  (Exception ex)
     {
         XXX.LogError(appName, ex);
     }
 
     CloseChildWindows();
}
 
 
private  void  CloseChildWindows()
{
     if  (pythonWindow !=  null )
     {
         pythonWindow.Closed -= ChildWindowClosed;
         pythonWindow.Close();
         pythonWindow =  null ;
     }
 
     ......
}         

注:該部分一些方法或變量是模擬的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM