WPF应用程序的生命周期

WPF应用程序的生命周期

废话不罗嗦看招:用户双击应用程序--->操作系统启动应用程序--->运行run函数程序启动--->触发一个Startup事件

先说到这让我们先分析一下以上运行周期
打开你新建的WPF应用程序,在App.xaml文件中,看到如下所示的代码
     /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {
    } 
转到Application的定义,你会看到Run函数,如下图所示
接下来让我们看看Startup事件的定义
OK,写的很清楚在Run()函数被调用之后紧接着就发生了,当然我们没有看到Startup函数,这只是定义
Startup事件在APP.xaml文件中声明
在App.xaml.cs文件中定义该事件处理函数,主要就做一见事,创建主窗口并显示,如下所示
private void Application_Startup(object sender,StartupEventArgs e)
{
    MainWindow win=new MainWindow();
    win.Show();
}
实际上在我们创建WPF程序的时候,VS已经帮我们做了更好的处理,我们是见不到如上所示的代码的
更好的处理就是将窗口的xaml文件赋值给Application对象的StartupUri属性
打开你新建的WPF应用程序,在App.xaml文件中你会看到如下所示的代码
StartupUri="MainWindow.xaml"
触发了Startup事件后,如果没有异常的话(当然不排除有异常的情况,这个我们暂且不表留待下文)主窗口就会呈现在你的面前,
Application调用Run函数应用程序进入消息循环,该循环不断的响应并处理事件,上面所讲的Startup事件就是应用程序的第一个事件,主要用来创建应用程序的主窗口界面。好了,走到这里应用程序就要面临两种状态,一种是激活状态(Activated)另一种就是非激活状态(Deactivated)这好比一个人在生活中要么是高调的状态,要么是低调的状态。一般来说,在桌面上只有一个窗口处在激活状态,就像舞台上一段时间内只有一部戏在演出,一个电视屏幕只有一个电视台你可以观看,当然了说的不包括现在的有些电视,拥有激活窗口的应用程序即激活状态,而其他在“台下”等着“上台”的应用程序则处在非激活状态,当然了现在所说的这些不管是激活状态的应用程序还是非激活状态的应用程序,都是建立在程序已经启动的前提下的哦。
大家都知道alt+Tab组合键的妙用,这正是用来切换应用程序的状态的。
对于这两个状态,WPF里有相应的事件来判断应用程序处于何种状态,同样在App.xaml文件中,若下所示让我们看一看这两个事件
同样打开App.xaml.cs文件来看看这两个事件的处理函数
 

异常登场

说到这我们该说说上文红字“异常”的处理了,人不可能无错,正如程序不可能没有bug,相信大家都在编程中遇到过异常,这里就不废话说异常带来的“灾难”了。不知道什么时候起“突发事件应急处理”这几个字开始活跃在报纸,新闻,广播中,WPF对于“突发事件应急处理”有自己的方法应对,DispacherUnhandledException事件就是异常出现时触发的事件,让我们用实例说话在App.xaml文件中

DispatcherUnhandledException="Application_DispatcherUnhandledException"
 DispatcherUnhandledException="Application_DispatcherUnhandledException"
同样在App.xaml.cs文件中我们来看看这个事件处理函数
  private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            MessageBox.Show("出错了,看你写的啥代码!!!");
        }
接着让我们制造些异常来看看是否会弹出提示
在MainWindow.xaml文件中写一个按钮Click事件
  private void Button_Click(object sender, RoutedEventArgs e)
        {
            Window win = null;
            win.Show();
        }

按Ctrl+F5启动应用程序,点击按钮,看到如下所示

 

当点击确定时,我们会看到应用程序还是立刻退出了,这是怎么回事?其实在DispatcherUnhandledException
中参数e的类型是DispatcherUnhandledExceptionEventArgs,让我们对它一探究竟同上F12转到定义就会看到,它有两个属性,如下:
  
 public sealed class DispatcherUnhandledExceptionEventArgs : DispatcherEventArgs
    {
        // 摘要:
        //     获取通过调度程序执行代码时引发的异常。
        //
        // 返回结果:
        //     异常。
        public Exception Exception { get; }
        //
        // 摘要:
        //     获取或设置是否已处理异常事件。
        //
        // 返回结果:
        //     如果异常已得到处理,则为 true;否则为 false。
        public bool Handled { get; set; }
    }

这两个属性我们在处理异常时都会用的到,刚才我们只是“拦截”了异常,但是没有处理,真正要做到处理,就要这样做,将e.Handled属性设置为true.

  private void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            e.Handled = true;
            MessageBox.Show("出错了,看你写的啥代码!!!");
        }
OK,Ctrl+F5再度运行程序,点击按钮,就会出现跳出和上面的图示。但是确定以后程序没有死掉。处理完以上我们因为编程不当出现的异常,我们就要说说另一种非正常的“异常”,有时由于我们不小心触发了计算机关机、重启、或注销时程序也会非正常死亡,这时应用程序也有一个事件SessionEnding, 在App.xaml文件中我们添加处理该异常的事件响应函数,在App.xaml.cs中实现该函数
App.xaml中对应代码:
SessionEnding="Application_SessionEnding"
App.xaml.cs中对应代码:
      private void Application_SessionEnding(object sender, SessionEndingCancelEventArgs e)
        {
           
        }

还没有写任何处理代码,先不急我们先来看看这个函数的参数。sender参数代表的是一个WPF应用程序,这个想必我不说大家也知道,那我们就来仔细分析一下第二个参数,F12转到该参数类的定义文件如下:

// 摘要:
    //     包含 System.Windows.Application.SessionEnding 事件的事件参数。
    public class SessionEndingCancelEventArgs : CancelEventArgs
    {
        // 摘要:
        //     获取一个值,该值指示会话结束的原因。
        //
        // 返回结果:
        //     指示会话结束的原因的 System.Windows.ReasonSessionEnding 值。
        public ReasonSessionEnding ReasonSessionEnding { get; }
    }
大家一看就明白了,我就不说废话了,ReasonSessionEnding 属性表示WPF程序结束的原因
它是一个类,让我们再探究一下这个类中写了什么,F12. ok,真相大白天下
  // 摘要:
    //     指定用户会话正在结束的原因。 由 System.Windows.SessionEndingCancelEventArgs.ReasonSessionEnding
    //     属性使用。
    public enum ReasonSessionEnding
    {
        // 摘要:
        //     会话正在结束的原因是用户正在注销。
        Logoff = 0,
        //
        // 摘要:
        //     会话正在结束的原因是用户正在关闭 Windows。
        Shutdown = 1,
    }

sorry,原来它是一个枚举,有两个值,很简单,再回过头来我们继续看SessionEndingCancelEventArgs 类。发现它继承CancelEventArgs,说到继承大家都清楚,子类继承父类就具有了父类的属性.让我们看看CancelEventArgs类:

 // 摘要:
        //     获取或设置指示是否应取消事件的值。
        //
        // 返回结果:
        //     如果应取消事件,则为 true;否则为 false。
        public bool Cancel { get; set; }

它就一个属性,Cancel。看到这,聪明的大家该知道如何写SessionEnding处理函数了吧。随便写写,如下:

 private void Application_SessionEnding(object sender, SessionEndingCancelEventArgs e)
        {
            e.Cancel = true;//阻止系统关机,重启或注销
            string msg = e.ReasonSessionEnding.ToString();//获取程序关闭的原因
        }

程序生命周期最后一步,【退出】

应用程序正常退出有三种情况即,关闭主窗口,关闭应用程序的所有窗口及调用ShutDown函数,然而这三种情况又是由我们设定Application的ShutDownMode属性值决定的

 

看上图,我们来一一解析三个值

OnExplicitShutdown:表示显示调用ShutDown函数关闭应用程序
OnLastWindowClose:表示关闭所有窗口时应用程序退出
OnMainWindowClose:表示关闭主窗口时应用程序退出
好,让我们来看看ShutDown函数
  //
        // 摘要:
        //     关闭一个应用程序。
        public void Shutdown();
        //
        // 摘要:
        //     关闭将指定退出代码返回给操作系统的应用程序。
        //
        // 参数:
        //   exitCode:
        //     应用程序的一个整数退出代码。 默认退出代码为 0。
        [SecurityCritical]
        public void Shutdown(int exitCode);

有两种重载,我们主要看第二种,奇怪为啥会有一个所谓的退出代码呢?还有它有什么用呢?

这个问题,下篇随笔再说。也希望知道的前辈指教一二,谢谢!~

posted @ 2013-04-27 21:59  阿磊ing  阅读(1831)  评论(0编辑  收藏  举报