|
|
|
|
研究异常(Exception)行为 我将很快给你看看从FileSearch3类中选取的代码。每次一个类的实例找到一个文件,实例就引发它的FileFound事件。这一效果导致.NET Framework相继地运行每个事件处理过程。看看下面的代码: ’’以下代码来自FileSearch3.vb这个技术的问题(正如你已经看到的)是:如果一个异常出现在任何一个侦听器中,异常回滚(bubbles back)到事件引发(event-raising)代码,.NET Framework不再调用事件侦听器,而事件处理就慢慢停了下来。 如果查看一下IL为示例代码所生成的,情况就变得清楚了。图 6 显示了在ILDASM中FileSearch3.Search方法的反汇编。你在类中看到的RaiseEvent语句直到一个FileFoundEventHandler.Invoke方法调用后才会编译。在内部,一旦这个方法已经调用,你的代码将控制权交给委托的执行过程,同时如果一个未处理的异常在调用列表的任何地方发生,这个异常回滚到调用者(这个代码),同时再没有侦听器获得调用。 这里有一个方案。胜于一再地简单调用RaiseEvent语句,它可能为你而显式地调用每个单独的侦听器。你可以利用Delegate类的成员以解决在多侦听器下的未处理异常问题。 手工调用每个侦听器 尽管RaiseEvent机制是方便的(并且也是令人觉得舒服的,如果你使用Visual Basic 6.0的话)它也有它的缺点,正如你所已经看到的。比依赖于RaiseEvent调用事件侦听器更好的是:你可以自己做这个工作。而你获得了一定的灵活性是你放弃使用RaiseEvent时的舒适为代价的。 如果你想要完全控制事件侦听器的调用而不只是希望事情如你所愿的方法解决,你将需要利用隐式的FileFoundEventHandler委托类型。你通过调用事件委托实例本身的GetInvocationList方法重新获得一个包含所有事件的侦听器的数组。一旦你有这个列表,你就可以独立地调用每个侦听器的Invoke方法,并且捕捉由事件处理程序引发的任何异常。如果任何侦听器引发一个异常,你就能处理它并将程序继续下去。 FileSearch4类包含其Search方法中的代码如图 7 显示。通过点击示例窗体上的GetInvocationList按钮运行这个代码。正如你将看到的,示例仍然调用引发一个错误的事件侦听器,但是既然这样,代码就不会在第一次侦听器引发错误时停止搜索文件。因为FileSearch4.Search方法包括独立地调用每个侦听器的代码,它也可以为每个调用处理异常。 ’ From FileSearch4.vbFileSearch4.Search中的新代码采取了以下动作: * 声明一个System.Delegate类型的数组以使得代码可以追踪到事件的所有侦听器: Dim ListenerList() As System.Delegate* 声明一个描述事件的委托类型的实例,以遍历侦听器数组(你应该记得:所有侦听器过程必须有其特定的类型,否则这个代码将不能被编译,这就是委托的工作方法): Dim Listener As FileFoundEventHandler* 重新获得侦听器列表,调用FileFoundEvent委托的内部GetInvocationList方法: ListenerList = FileFoundEvent.GetInvocationList()* 找到文件并遍历包含cor-responding FileInfos的数组,正如你前面已经看到的一样: Dim afi() As FileInfo = diLocal.GetFiles(Me.FileSpec)* 每找到一个文件,FileSearch4.Search就遍历事件侦听器的列表并独立地调用每个委托的回调(Invoke)方法。这允许代码捕捉(而且既然这样,就忽略)任何由每个独立地的侦听器引发的异常。 For Each Listener In ListenerList
|

