.net 异常和状态管理(2)

       关于异常的发生有意见好事在于,未处理异常会造成应用程序终止。之所以说这是一件好事,是因为可以在测试期间快速发现问题。利用由未处理的异常提供的信息(错误信息和堆栈跟踪),通常足以完成对代码的修正。当然,许多开发人员不希望他们的应用程序在测试和部署之后继续发生意外终止的情况,所以他们会插入代码来捕捉System.Exception,也就是所有异常类型的基类。然而,如果捕捉System.Exception并允许应用程序继续运行,一个很大的问题是状态可能遭受破坏。
为了缓解对状态的破坏,可以做下面几件事情:
1,可以用System.Diagnostics.Contracts.Contract 类向方法应用代码契约。利用代码契约,在用实参和其他变量对状态进行修改之前,可以先对这些实参/变量进行验证。如果实参/变量遵守契约,状态被破坏的可能性将大幅降低(但不能完全消除)。如果不遵守契约,那么异常会在任何状态被修改之前抛出。
2,可以使用约束执行区域(Constrained Execution Region, CER), 它提供了消除一些CLR不确定性的一种方式。例如,进入一个try块之前,可以让CLR加载与这个try块关联的任何catch和finally块所需要的程序集。除此之外,CLR会编译catch和finally块中的所有代码,包括从这些块中调用的所有方法。这样以来,在尝试执行catch块的错误恢复代码或者finally块中的(资源)清理代码时,就可以消除众多潜在的异常。它还减少了发生OutOfMemoryException和其他一些异常的几率。
3,取决于状态存在于何处,可利用事物(transaction)来确保状态要么都被修改,要么都不修改。例如,如果数据在数据库中,事务可以很好地工作。Windows现在还支持事务式的注册表和文件操作(仅限NTFS卷),所以也许能利用它。但是 .NET Framework目前没有直接公开这个功能。必须P/Invoke 本地代码才行。请参见System.Transactions.TransactionScope类了解细节。
4,将自己的方法设计得更明确。例如,Monitor类一般像下面这样获取/释放线程同步锁:

public static class SomeType{
	private static object myLockObject =new Object();
	public static void SomeMethod(){
		Monitor.Enter(myLockObect); // 如果抛出异常,是否获取了锁? 
									// 如果已经获取了锁,它就得不到释放!
		try{
			//在这里执行线程安全的操作........
		}
		finally{
			Monitor.Exit(myLockObject);
		}
	}
	//...
}

由于存在前面展示的问题,所以在这个重载的Monitor的Enter方法已经不再鼓励使用。建议像下面这样重写以上代码:

public static class SomeType{
	private static object myLockObject =new Object();
	public static void SomeMethod(){
		Boolen lockTaken = false; // 假定没有获取锁 
		try{
			// 无论是否抛出异常,以下代码都能正常工作!
			Monitor.Enter(myLockObject, ref lockTaken);
			// 在这里执行线程安全的操作.....
		}
		finally{
			if(lockTaken) Monitor.Exit(myLockObject);
		}
	}
	//...
}

虽然以上代码使方法变得更明确,但在线程同步锁的情况下,现在的建议是根本不要随同异常处理使用他们。

在代码中,如果确定状态已经损坏到无法修复的程度,就应销毁所有损坏的状态,防止它造成更多的伤害。然后重启应用程序,将状态初始化到一个良好的状态,并寄希望于状态不被损坏。由于托管的状态不能泄露到一个AppDomain的外部,所以为了销毁一个AppDomain中所有损坏的状态,可以调用AppDomain的Unload方法来卸载整个AppDomain.

如果觉得状态过于糟糕,以至于整个进程都应该停止,那么英爱调用Environment的静态FailFast方法。
此方法提供了一个进行清理的机会,FailFast方法将消息字符串和可选的异常(通常时catch块中捕捉的异常)发送给Windows Application事件日志,生成一个windows错误报告,创建应用程序的一个内存dump,然后终止当前线程。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值