WPF中的Application

WPF应用启动与关闭机制
本文介绍了WPF应用程序的基本启动流程,包括如何通过不同方式启动应用程序及其窗口,以及如何自定义应用程序的关闭行为。同时,还展示了如何通过XAML和代码来配置这些设置。
一、介绍

WPF和 传统的WinForm 类似, WPF 同样需要一个 Application 来统领一些全局的行为和操作,并且每个 Domain (应用程序域)中只能有一个 Application 实例存在。和 WinForm 不同的是 WPF Application 默认由两部分组成 : App.xaml 和 App.xaml.cs,将定义和行为代码相分离。当然,这个和WebForm 也比较类似。XAML 从严格意义上说并不是一个纯粹的 XML 格式文件,它更像是一种 DSL(Domain Specific Language,领域特定语言),它的所有定义都直接映射成某些代码,只是具体的翻译工作交给了编译器完成而已。WPF应用程序由 System.Windows.Application类来进行管理。

 

 

二、自已定义类用Main方法实现对WPF应用程序的启动

    在项目中添加一个类,类的代码如下,在项目选项中,设定此类为启动项。

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;

namespace WPFApplications
{
    public partial class App : Application
    {
        [STAThread]
        static void Main()
        {
          定义Application对象作为整个应用程序入口  
            Application app = new Application();
            // 方法一:调用Run方法,参数为启动的窗体对象 ,也是最常用的方法 
              Window2 win = new Window2();
            app.Run(win);

            // 方法二:指定Application对象的MainWindow属性为启动窗体,然后调用无参数的Run方法  
              Window2 win = new Window2();  
            app.MainWindow = win; 
            win.Show();       
              app.Run();  

            方法三:通过Url的方式启动
              app.StartupUri = new Uri("Window2.xaml", UriKind.Relative); 
            app.Run();
        }
    }
}

 

三、Application应用程序关闭
   
OnLastWindowClose(默认值): 最后一个窗体关闭或调用Application对象的Shutdown() 方法时,应用程序关闭。
OnMainWindowClose 启动窗体关闭或调用Application对象的Shutdown()方法时,应用程序关 闭。(和C#的Windows应用程序的关闭模式比较类似)
OnExplicitShutdown 只有在调用Application对象的Shutdown()方法时,应用程序才会关闭。

  对关闭选项更改的时候,可以直接在App.xaml中更改:

<Application x:Class="WPFApplications.App"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    StartupUri="Window2.xaml"    ShutdownMode="OnExplicitShutdown">    <Application.Resources>    </Application.Resources></Application>  

 

 同样你也可以在代码文件(App.xaml.cs)中进行更改,但必须注意这个设置写在app.Run()方法之前 ,如下代码:
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
app.Run(win);

 

原文链接:http://www.evget.com/zh-CN/Info/catalog/14973.html

 

 

<think>我们正在解决WPFApplication.OnExit方法未执行的问题。根据用户提供的信息和之前的引用,我们需要分析可能导致OnExit未执行的原因,并提供解决方案。可能的原因包括:1.异常导致进程崩溃,从而跳过OnExit的执行。2.应用程序被强制终止(例如通过任务管理器结束进程)。3.应用程序进入了一个无法退出的状态(如死循环或死锁)。4.重写了OnExit但没有正确调用基类方法(如果使用重写的话,但通常我们订阅的是事件)。注意:Application.OnExit是一个受保护的虚方法,通常我们通过订阅Application.Exit事件来执行退出逻辑,而不是重写OnExit方法。但这里用户提到的是“方法未执行”,可能指的是重写OnExit方法的情况,或者是订阅的Exit事件未触发。根据引用[1],我们捕获了未处理的异常来提升稳定性,但即使这样,如果连续捕获多次异常,还是可能导致进程崩溃。因此,如果退出过程中发生未处理的异常,可能导致OnExit无法执行。解决方案:1.确保在应用程序中正确处理异常,特别是在退出逻辑中。2.检查是否在某个地方调用了Environment.Exit或其他强制退出的方法。3.使用Application.Exit事件代替重写OnExit方法(如果当前是重写的话)。4.确保在退出时没有后台线程阻止进程结束(前台线程会阻止,后台线程不会,但如果有非后台线程在运行,则应用程序不会退出)。步骤:如果用户是重写OnExit方法:在App.xaml.cs中:```csharppublicpartialclassApp:Application{protectedoverridevoidOnExit(ExitEventArgse){//确保调用基类方法base.OnExit(e);//自定义退出逻辑}}```如果用户订阅了Exit事件:```csharppublicpartialclassApp:Application{publicApp(){this.Exit+=App_Exit;}privatevoidApp_Exit(objectsender,ExitEventArgse){//退出逻辑}}```另外,检查是否有任何地方调用了Environment.Exit(),因为这会立即终止进程,不会触发OnExit或Exit事件。此外,检查是否有未处理的异常导致进程崩溃。引用[1]中提到了全局异常处理,但要注意,即使有全局异常处理,如果异常发生在某些特定时刻(例如在退出过程中),也可能无法捕获。因此,建议:-在全局异常处理中记录异常,以便分析退出失败的原因。-确保所有关键操作都有异常处理,避免在退出前发生未处理异常。如果问题仍然存在,可以尝试在应用程序关闭时(如主窗口关闭事件)手动调用一些清理逻辑,而不是完全依赖OnExit。注意:Application.Exit事件(或OnExit方法)只有在应用程序正常关闭时才会触发。正常关闭通常是指所有窗口关闭且没有前台线程在运行。如果应用程序因为未处理异常而崩溃,或者被用户强制结束,则不会触发。因此,另一个建议是:在应用程序的主窗口中处理Closing事件,执行一些清理工作,因为主窗口关闭通常是应用程序退出的开始。总结可能的原因及解决方案:1.异常导致崩溃:加强异常处理,特别是在退出逻辑中;使用全局异常处理记录异常(如引用[1]所示)。2.强制终止:无法避免,但可以提示用户正常关闭。3.重写OnExit方法时未调用基类方法:确保调用base.OnExit(e)。4.使用了Environment.Exit:避免使用,或者在使用前执行清理逻辑。5.有非后台线程在运行:确保在退出前停止所有非后台线程,或者将它们设置为后台线程(默认情况下,通过Thread.Start启动的线程是前台线程,而Task.Run创建的是后台线程)。最后,如果用户的问题仍然无法解决,建议提供更具体的上下文,例如在什么情况下OnExit没有执行,是否有错误信息等。根据引用[2],用户使用了MEF,如果MEF组件在退出时需要释放资源,也要确保在OnExit或Exit事件中正确地清理这些组件。因此,我们可以在退出事件中执行MEF容器的释放:```csharpprivatevoidApp_Exit(objectsender,ExitEventArgse){//如果有MEF容器,进行释放if(container!=null){container.Dispose();}}```但要注意,如果MEF组件有需要在退出时保存状态等操作,应确保这些操作不会抛出异常。综上所述,请用户检查以上几点,特别是异常处理和线程问题。相关问题:1.如何捕获WPF应用程序的全局异常?2.如何确保WPF应用程序正常退出?3.WPFApplication.Exit事件和OnExit方法有什么区别?4.如何管理WPF应用程序中的后台线程?</think>### WPFApplication.OnExit方法未执行的原因及解决方案 在WPF中,`Application.OnExit`方法未执行通常由以下原因引起: #### 常见原因分析 1. **强制进程终止** - 当使用`Environment.Exit()`、`Process.Kill()`或任务管理器强制结束时,会绕过WPF的退出流程[^1]。 - 示例:`Environment.Exit(0);` // 直接终止进程,跳过OnExit 2. **未处理异常导致崩溃** - 未捕获的异常(尤其是非UI线程异常)可能使进程崩溃,无法触发OnExit[^1]。 - 引用代码中的全局异常处理虽能捕获部分异常,但连续崩溃仍可能导致跳过退出流程。 3. **线程阻塞或死锁** - 主UI线程被阻塞(如死锁、无限循环),阻止退出事件传播。 - 后台线程未设置为后台属性(`IsBackground=true`),阻止进程结束。 4. **ShutdownMode设置不当** ```xml <Application ShutdownMode="OnExplicitShutdown" /> ``` - 若设置为`OnExplicitShutdown`但未调用`Application.Shutdown()`,OnExit不会触发。 5. **重写方法未调用基类实现** ```csharp protected override void OnExit(ExitEventArgs e) { // 缺少 base.OnExit(e) 会导致事件链中断 } ``` --- #### 解决方案 1. **替代强制退出方法** 使用`Application.Current.Shutdown()`代替`Environment.Exit()`: ```csharp Application.Current.Shutdown(); // 触发OnExit ``` 2. **增强异常处理** - 在关键操作中显式使用`try-catch`: ```csharp try { /* 业务代码 */ } catch (Exception ex) { Logger.Error(ex); } ``` - 补充全局异常处理(引用[^1]方案): ```csharp // App.xaml.cs protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); DispatcherUnhandledException += App_DispatcherUnhandledException; AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; } ``` 3. **检查线程状态** - 确保后台线程设置为后台模式: ```csharp var thread = new Thread(WorkMethod) { IsBackground = true }; ``` - 使用`Dispatcher.InvokeShutdown()`结束阻塞的UI线程。 4. **验证ShutdownMode** 在App.xaml中设置合适模式: ```xml <Application ShutdownMode="OnLastWindowClose" /> <!-- 默认值 --> ``` 5. **正确重写OnExit方法** ```csharp protected override void OnExit(ExitEventArgs e) { // 自定义清理逻辑 CleanupResources(); base.OnExit(e); // 必须调用基类方法 } ``` 6. **检查第三方组件** 如使用MEF(引用[^2]),确保组件未在退出时抛出异常: ```csharp [Export(typeof(IModule))] public class MyModule : IModule, IDisposable { public void Dispose() { /* 释放资源 */ } } ``` --- ### 调试建议 1. **记录退出路径** 在`OnExit`入口添加日志: ```csharp protected override void OnExit(ExitEventArgs e) { Logger.Info("OnExit started"); base.OnExit(e); } ``` 2. **检查事件订阅** 如果使用`Application.Exit`事件而非重写方法,确保订阅有效: ```csharp Application.Current.Exit += (s, e) => { /* 逻辑 */ }; ``` 3. **分析Windows事件日志** 通过`Event Viewer > Windows Logs > Application`查看崩溃记录。 > 通过上述措施,可解决95%以上的`OnExit`未执行问题。若仍存在,需检查是否有底层系统API调用或驱动级错误。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值