课程名:Windows应用程序开发入门到精通七:优化.NET异常处理
1.多个catch块的情况时会过滤异常,先截获具体的异常,再截获一般的异常,并且这是从编译器的层次就支持的。
2.应该从系统异常(System.ApplicationException)派生自己的具体异常,从而为特定的应用程序提供更好的支持。
3.异常处理技术:1)记录异常:在文件中记录异常;在数据库中记录;在Eventlog中记录。2)发email等信息来通知异常。总之,要以用户友好的方式通知异常的发生。
4.使用Application对象中的ThreadException属性来设置一个delegate来捕获所有未处理的主线程中出现的异常,但并不能处理你自己创建的工作进程中出现的异常。
public static void Main(string[] args)

{
Application.ThreadException += new
ThreadExceptionEventHandler(
MainUIThreadExceptionHandler);
Demo6();

System.Windows.Forms.Application.Run(
new NorthwindMDIMain());
}

public static void MainUIThreadExceptionHandler(
Exception e)

{
MainUIThreadExceptionHandler(null, new System.Threading.
ThreadExceptionEventArgs(e));
}

public static void MainUIThreadExceptionHandler(object
sender, ThreadExceptionEventArgs t)

{

ExceptionManager.Publish(t.Exception);

//Tell the user a boo-boo occurred
MessageBox.Show(
"Northwind Orders has encountered the following "
+ " problem:" + (char)13
+ (char)13 + t.Exception.Message
+ (char)13 + (char)13
+ "Please contact your administrator or the "
+ "Northwind Help desk at "
+ (char)13 + (char)13 +"1-855-555-5555."
+ (char)13 + (char)13
+ "We apologize for the inconvenience."
, "Northwind Orders Encountered a Problem"
, MessageBoxButtons.OK
, MessageBoxIcon.Error
, MessageBoxDefaultButton.Button1
, MessageBoxOptions.ServiceNotification);
}

5,必须考虑在工作线程中出现的异常,在线程的入口使用try-catch,并且使用delegate等方式将异常通知给主线程,此外,线程之间要访问对方的界面成员时,应该通过BeginInvoke()方法来进行。
public delegate void DoneDelegate(bool Stopped);
public delegate void
WorkerThreadExceptionHandlerDelegate(Exception e);
void WorkerThreadExceptionHandler(Exception e)

{
UpdateProgress();
SetStatusText("Problem Encountered");
this.Text = "Customers";
btnSave.Text = "Save";
btnClose.Enabled = true;
//Call the global exception handler
MainClass.MainUIThreadExceptionHandler(
this, new System.Threading.
ThreadExceptionEventArgs(e));
}
private void btnSave_Click(object sender, System.EventArgs e)

{
try

{
if(true==btnSave.Enabled)

{
this.Text = "Customers (Saving
)";
btnSave.Enabled=false;
btnClose.Enabled=false;
System.Threading.Thread t =
new System.Threading.Thread(
new System.Threading.ThreadStart(
SaveCustomer));
t.Start();
}
else

{
isCanceled = true;
btnSave.Enabled = true;
}
}
catch(NotSupportedException exception)

{
MessageBox.Show("Code not done yet "
+ exception.Message
);
}
catch(Exception exception)

{
//Tell the user a boo-boo occurred
MainClass.MainUIThreadExceptionHandler(this
,new System.Threading.
ThreadExceptionEventArgs(exception));
MessageBox.Show(
"Northwind Orders has encountered a problem. "
+ "Please contact your administrator or the "
+ "Northwind Help desk at "
+ (char)13 + (char)13 +"1-855-555-5555."
+ (char)13 + (char)13
+ "We apologize for the inconvenience."
, "Northwind Orders Encountered a Problem"
, MessageBoxButtons.OK
, MessageBoxIcon.Error);
}
finally

{
this.Cursor=Cursors.Default;
}
}
private void SaveCustomer()

{
try

{
SetStatusText(
"Saving record on a background thread
");

//TODO: Add code to save the customer record
this.BindingContext[dsCustomers,"Customers"].
EndCurrentEdit();
dsCustomers objDataSetChanges = ((dsCustomers)
(dsCustomers.GetChanges()));
if(null!=objDataSetChanges)
new NorthwindDataAccess().UpdateCustomers(
objDataSetChanges);

isCanceled = false;
DoneDelegate delDone = new DoneDelegate(Done);
delDone.BeginInvoke(isCanceled, null, null);

}
catch(Exception e)

{
new WorkerThreadExceptionHandlerDelegate(
WorkerThreadExceptionHandler).BeginInvoke(e
,null
,null);
}
}
private void Done (bool Stopped)

{

UpdateProgress();
this.Text = "Customers";
btnSave.Enabled=true;
btnClose.Enabled=true;
if(Stopped)

{
MessageBox.Show("Save Stopped"
, "Stopped"
, MessageBoxButtons.OK
, MessageBoxIcon.Warning);
SetStatusText("Save Stopped");
}
else

{
MessageBox.Show("Save Done"
, "Done"
, MessageBoxButtons.OK
, MessageBoxIcon.Information);
SetStatusText("Save Done");
}
}

6,在构造函数中不要加try-catch,因为这会把异常再抛给外部方法,还不如不处理,直接抛给外部好了。
7,异常处理程序块采用的是publisher/subscriber设计模式,在工程中添加对它的引用,并引入名称空间Microsoft.ApplicationBlocks.ExceptionManagement就可以使用ExceptionManager.Publish()来进行异常的发布。在app.config中可以对异常管理进行启/停,还可以添加自己的异常处理模块。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="exceptionManagement"
type="Microsoft.ApplicationBlocks.ExceptionManagement.ExceptionManagerSectionHandler,Microsoft.ApplicationBlocks.ExceptionManagement" />
</configSections>

<exceptionManagement mode="on">
<publisher mode="on" assembly="Microsoft.ApplicationBlocks.ExceptionManagement"
type="Microsoft.ApplicationBlocks.ExceptionManagement.DefaultPublisher"
logname="Northwind Exceptions Log"
applicationname="Northwind Traders Orders" />
</exceptionManagement>

</configuration>

public static void MainUIThreadExceptionHandler(object
sender, ThreadExceptionEventArgs t)

{

ExceptionManager.Publish(t.Exception);

//Tell the user a boo-boo occurred
MessageBox.Show(
"Northwind Orders has encountered the following "
+ " problem:" + (char)13
+ (char)13 + t.Exception.Message
+ (char)13 + (char)13
+ "Please contact your administrator or the "
+ "Northwind Help desk at "
+ (char)13 + (char)13 +"1-855-555-5555."
+ (char)13 + (char)13
+ "We apologize for the inconvenience."
, "Northwind Orders Encountered a Problem"
, MessageBoxButtons.OK
, MessageBoxIcon.Error
, MessageBoxDefaultButton.Button1
, MessageBoxOptions.ServiceNotification);
}

可以在“事件查看器”中看到异常已经发布进来了:

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述