WPF/C#:异常处理
什么是异常?
在C#中,异常是在程序执行过程中发生的特殊情况,例如尝试除以零、访问不存在的文件、网络连接中断等。这些情况会中断程序的正常流程。
当C#程序中发生这种特殊情况时,会创建一个异常对象并将其抛出。这个异常对象包含了关于异常的详细信息,如异常类型和异常发生时的程序状态。
异常处理是一个重要的编程概念,它允许程序员在异常发生时采取适当的行动,而不是让程序崩溃。在C#中,我们使用try,catch和finally关键字来处理异常。
比如,下面的代码用0除一个数时,会出现一个异常:
internal class Program
{static void Main(string[] args){int x = 10, y = 0;x /= y;}
}
try语句
try语句用来指明为避免出现异常而被保护的代码段,并在发生异常时提供代码处理异常。try语句由3个部分组成,如下图所示:
处理异常
上面除以0会导致一个异常的程序,可以进行如下改写,进行异常处理:
internal class Program
{static void Main(string[] args){int x = 10;try{int y = 0;x /= y;}catch{Console.WriteLine("Handling all exceptions");}}
}
异常被捕获:
异常类
在C#中,所有的异常都是派生自System.Exception类的。System.Exception类是所有异常的基类,它提供了一些基本的功能,如返回错误消息和记录异常发生的堆栈跟踪。
C#提供了一些内置的异常类,用于表示常见的异常情况。例如:
- System.NullReferenceException:当你试图访问一个null对象的成员时,会抛出这个异常。
- System.DivideByZeroException:当你试图除以零时,会抛出这个异常。
- System.IndexOutOfRangeException:当你试图访问数组或集合的无效索引时,会抛出这个异常。
- System.IO.FileNotFoundException:当试图打开的文件不存在时,会抛出这个异常。
当一个异常发生时,CLR会创建该类型的异常对象,并寻找适当的catch子句处理它。
所有异常类从根本上派生自System.Exception类,异常继承层次的一个部分如下所示:
catch子句
catch子句处理异常。它有3种形式,允许不同级别的处理,如下图所示:
- 一般catch子句:这种形式的catch子句可以捕获任何类型的异常。它不指定异常类型,所以它会捕获try块中抛出的所有异常。
- 特定catch子句:这种形式的catch子句只捕获指定类型的异常。如果try块中抛出的异常类型与catch子句中指定的类型匹配,那么就会执行这个catch子句。
- 带对象的特定catch子句:这种形式的catch子句不仅指定了异常类型,还定义了一个异常对象。这个异常对象可以用来访问关于异常的更多信息,如错误消息和堆栈跟踪。
将开头的例子,修改为使用带对象的特定catch子句,如下所示:
internal class Program{static void Main(string[] args){int x = 10;try{int y = 0;x /= y;}catch(DivideByZeroException e){Console.WriteLine($"Message:{e.Message}");Console.WriteLine($"Source: {e.Source}");Console.WriteLine($"Stack: {e.StackTrace}");} }}
输出结果如下所示:
抛出异常
可以使用throw语句使代码显式地引发一个异常。throw语句的语法如下:
throw ExceptionObject;
好了,以上就是C#中关于异常处理的基础知识,现在我们结合WPF中的例子说明在WPF中如何进行异常处理的。
WPF中的异常处理
现在来看看ExceptionHandlingSecondaryUIThread这个例子,项目结构如下图所示:
先来看一下这个项目的运行效果:
这个例子介绍了WPF中如何处理在辅助UI线程中发生的异常。
现在来看看是如何处理的。
StartSecondaryUIThreadButton
按钮点击事件处理程序:
private void startSecondaryUIThreadButton_Click(object sender, RoutedEventArgs e){// Creates and starts a secondary thread in a single threaded apartment (STA)var thread = new Thread(MethodRunningOnSecondaryUIThread);thread.SetApartmentState(ApartmentState.STA);thread.IsBackground = true;thread.Start();}
这段代码的主要目的是创建并启动一个新的辅助UI线程。
thread.SetApartmentState(ApartmentState.STA);
这行代码设置了线程的公寓状态为STA(Single-Threaded Apartment)。在WPF中,所有的UI线程都必须是STA线程,因为UI元素不是线程安全的。
Single-Threaded Apartment(STA)介绍
在WPF(Windows Presentation Foundation)中,Single-Threaded Apartment(STA)是指一个线程模型,其中每个线程都维护自己的消息队列,并且所有的UI操作都在这个线程上进行。
在STA模型中,每个线程都有自己的内存空间,这意味着线程之间的数据不会共享,从而避免了多线程编程中的许多并发问题。这对于UI编程来说非常重要,因为UI元素通常不是线程安全的,所以所有的UI操作都必须在同一个线程上进行。
在WPF中,主UI线程默认就是一个STA线程。此外,你也可以创建其他的STA线程,但是每个STA线程都只能操作它自己创建的UI元素。
MethodRunningOnSecondaryUIThread
方法如下所示:
// THIS METHOD RUNS ON A SECONDARY UI THREAD (THREAD WITH A DISPATCHER)private void MethodRunningOnSecondaryUIThread(){var secondaryUiThreadId = Thread.CurrentThread.ManagedThreadId;try{// On secondary thread, show a new Window before starting a new Dispatcher// ie turn secondary thread into a UI threadvar window = new SecondaryUIThreadWindow();window.Show();Dispatcher.Run();}catch (Exception ex){// Dispatch the exception back to the main ui thread and reraise itApplication.Current.Dispatcher.Invoke(DispatcherPriority.Send,(DispatcherOperationCallback) delegate{// THIS CODE RUNS BACK ON THE MAIN UI THREADstring msg = $"Exception forwarded from secondary UI thread {secondaryUiThreadId}.";throw new Exception(msg, ex);}, null);// NOTE - Application execution will only continue from this point// onwards if the exception was handled on the main UI thread// by Application.DispatcherUnhandledException}}
在try语句块中创建了SecondaryUIThreadWindow。
SecondaryUIThreadWindow上的按钮的点击事件处理程序如下所示:
private void raiseExceptionOnSecondaryUIThreadButton_Click(object sender, RoutedEventArgs e){// Raise an exception on the secondary UI threadstring msg = $"Exception raised on secondary UI thread {Dispatcher.Thread.ManagedThreadId}.";throw new Exception(msg);}
抛出了一个异常。
这个异常被MethodRunningOnSecondaryUIThread
方法中的catch子句段捕获:
Application.Current.Dispatcher.Invoke(DispatcherPriority.Send,(DispatcherOperationCallback) delegate{// THIS CODE RUNS BACK ON THE MAIN UI THREADstring msg = $"Exception forwarded from secondary UI thread {secondaryUiThreadId}.";throw new Exception(msg, ex);}, null);
这段代码的主要目的是在辅助UI线程上捕获异常,并将异常转发到主UI线程上进行处理。
在app.xaml中
DispatcherUnhandledException="App_DispatcherUnhandledException"
这行代码是在WPF应用程序中设置全局未处理异常的处理器。
当应用程序的主调度器捕获到未处理的异常时,App_DispatcherUnhandledException方法会被调用来处理这个异常。
这是一种处理全局未处理异常的方式,可以防止应用程序因为未处理的异常而崩溃。在App_DispatcherUnhandledException方法中,你可以记录异常信息,显示错误消息,或者决定是否让应用程序继续运行。
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e){// Display exception messagevar sb = new StringBuilder();sb.AppendFormat("{0}\n", e.Exception.InnerException.Message);sb.AppendFormat("{0}\n", e.Exception.Message);sb.AppendFormat("Exception handled on main UI thread {0}.", e.Dispatcher.Thread.ManagedThreadId);MessageBox.Show(sb.ToString());// Keep application running in the face of this exceptione.Handled = true;}
这样就完成了在WPF中的辅助UI线程的异常处理。
还有一个例子是ExceptionHandlingSecondaryWorkerThread说明在WPF中如何处理在辅助工作线程(Secondary Worker Thread)中发生的异常,与这个例子类似。
参考
1、《C#图解教程》
2、[WPF-Samples/Application Management/ExceptionHandlingSecondaryUIThread at main · microsoft/WPF-Samples (github.com)](https://github.com/microsoft/WPF-Samples/tree/main/Application Management/ExceptionHandlingSecondaryUIThread)
相关文章:

WPF/C#:异常处理
什么是异常? 在C#中,异常是在程序执行过程中发生的特殊情况,例如尝试除以零、访问不存在的文件、网络连接中断等。这些情况会中断程序的正常流程。 当C#程序中发生这种特殊情况时,会创建一个异常对象并将其抛出。这个异常对象包…...

2024年跨平台应用解决方法
个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 很久没有写这类high-level的文章了,本身这类框架就一直层出不穷,但是其中历久弥坚,坚韧不拔的框架又有多少呢? 首先考虑到学习成本以及掌握一些编程语言在工作、学习生态上的价值,给这些东西适用生态划分一下. Reac…...

人工智能ChatGPT的多种应用:提示词工程
简介 ChatGPT 的主要优点之一是它能够理解和响应自然语言输入。在日常生活中,沟通本来就是很重要的一门课程,沟通的过程中表达的越清晰,给到的信息越多,那么沟通就越顺畅。 和 ChatGPT 沟通也是同样的道理,如果想要 …...
OceanBase v4.2 解读:tenant=all 语义优化,提升易用性
1 背景 1.1 租户类型及特点 OceanBase中有三种类型的租户: sys租户:集群默认创建,生命周期与集群相一致,管理集群和其他租户,具有较高的地位。用户租户:用户创建的业务租户或普通租户,用于运…...
理论和实验
一、理论和实验的关系 (一)理论可以指导实验 理论家提出理论和猜想,实验家就可以做个实验来验证是否适用。 (二)实验可以提升理论认识 实验家通过做实验,观察实验过程和结果后,如果发现和理论预测有误差,那么理论家就能根据新发现…...
Linux 常用命令 - userdel 【删除用户】
简介 userdel 这个命令源自于 “user delete”,即用户删除。这个命令主要用于在 Linux 系统中删除用户账户及其相关文件。当管理员需要移除一个用户及其在系统中的所有踪迹时,会用到这个命令。 使用方式 userdel [选项] 用户名常用参数 -f:强制删除用户,即使用户当前已登…...
等保测评和安全运维
# 等保测评与安全运维:构建企业网络安全的双重保障 引言 在数字化时代,企业面临着日益复杂的网络安全威胁。为了应对这些挑战,企业不仅要实施有效的安全运维措施,还需要通过等保测评确保其信息系统符合国家的安全标准。本文将探讨…...

Java课程设计:基于Java+Swing+MySQL的图书管理系统(内附源码)
文章目录 一、项目介绍二、项目展示三、源码展示四、源码获取 一、项目介绍 图书管理系统是一个常见的软件项目,广泛应用于图书馆、学校、企业等需要管理图书资源的场景。该系统通常涵盖图书信息录入、查询、借阅、归还等核心功能,是实现图书资源高效管理的重要工具。 随着信…...
WireGuard网络架构及配置详解
WireGuard网络架构及配置详解 一.点对点二.中心网关,实现nat穿透弊端:流量全部经过中心网关,带宽上限受限于中心网关 三.借助registry实现双向nat穿透需要借助registry实现 udp打洞, 待二开 一.点对点 yum install epel-release elrepo-release -y yum install yum-plugin-elr…...

VB.NET实现上位机自动识别可用串口
在实际应用中有时会牵扯到挑选可用串口,比如上位机和从站设备使用Modbus RTU协议进行通讯时需要选择COM串口,每次启动连接前都在设备管理器查看较为麻烦,可以设置一个串口自动识别功能,如果选择了错误的串口还可以提示串口选择错误…...

Node.js版本管理工具-NVM
在开发 Node.js 项目时,经常会遇到需要切换不同版本的 Node.js 的情况。为了方便管理和切换各个版本,我们可以使用一些 Node.js 版本管理工具。 Node Version Manager:简称NVM,最流行的 Node.js 版本管理工具之一。它允许我们在同…...
【react】useEffect 快速上手
useEffect 快速上手 useEffect(setup, dependencies?) 可以接收两个参数,分别是回调函数与依赖数组. useEffect 用什么姿势来调用,本质上取决于你想用它来达成什么样的效果。下面我们来简单介绍 useEffect 的调用规则。 每一次渲染后都执行的副作用&a…...
docker容器部署jenkins
提前安装好jdk和maven,jdk最好使用11版本,jdk-11.0.10 docker run -u root -d \ -p 100:8080 \ -v /var/jenkins_home/workspace/:/var/jenkins_home/workspace/ \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /usr/bin/docker:/usr/bin/docker…...

第十四章 享元模式
目录 1 享元模式介绍 2 享元模式原理 3 享元模式实现 4 享元模式应用实例 5 享元模式总结 1 享元模式介绍 享元模式 (flyweight pattern) 的原始定义是:摒弃了在每个对象中保存所有数据的方式,通过共享多个对象所共有的相同状态,从而让我…...

ThinkBook 16 2024 Ubuntu 触控板问题解决
sudo insmod goodix-gt7868q.ko sudo cp local-overrides.quirks /etc/libinput/local-overrides.quirks sudo systemctl restart gdm 有偿解决,无效退款...
qt qDebug兼容LOGE
目录 普通qDebug用法 qt qDebug兼容LOGE 模板参数2实现 qDebug 实现LOGE一样的用法,这样Android和qt同时支持LOGE打印日志 普通qDebug用法 #include <QApplication> #include <QDebug>int main(int argc, char *argv[]) {QApplication app(argc, argv);int ret…...

【Ardiuno】实验使用ESP32单片机连接Wifi(图文)
ESP32单片机最为精华和有特色的地方当然是wifi连接,这里我们就写程序实验一下适使用ESP32主板连接wifi,为了简化实验我们这里只做了连接部分,其他实验在后续再继续。 由于本实验只要在串口监视器中查看结果状态即可,因此电路板上…...
常用的五大数据可视化工具测评分享
随着数据驱动决策的时代到来,数据可视化工具成为了企业提升数据分析效率和决策质量的关键工具。本文将对帆软BI、奥威BI、思迈特BI、永洪BI以及亿信华辰BI这五大数据可视化工具进行详细的操作体验测评,总结它们的特点和优势。 一、帆软BI 帆软BI作为国…...

什么是校园抄表系统?
1.校园抄表系统的简述 校园抄表系统是当代高校管理中的一个重要组成部分,主要运用于全自动搜集、管理方法与分析校园里的电力能源使用数据,如水电煤等。它通过先进的方式方法,完成了对能源消耗的实时监控系统,提升了电力能源管理…...

计算机专业:未来何去何从?
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...