这个陷阱来自于一个需求:需要异步在后台处理数据,处理完后触发处理完成的事件,大概是这么写的:
  EmployeeCollection data = new EmployeeCollection();
  data.Loaded += data_Loaded;
  Action<EmployeeCollection> action = (d) => {
  DalHelper.Fill(data);
  data.RaiseEventLoaded();
  };
  action.BeginInvoke(data, null, null);
  挺简单的代码,陷阱也在其中。假如DalHelper.Fill(data)抛出了一个异常,那么对data.RaiseEventLoaded()就不会执行,依赖于data.Loaded事件的代码也不会执行,这是一个bug,应该在委托执行中加入一个try…catch语句,或者在某个地方调用委托的EndInvoke方法,来处理执行中可能的异常。
  为了这么一个简单的需求,加入try…catch或者调用委托的EndInvoke都太复杂了,仅仅只想满足假如执行失败,就把异常抛出来,即使将当前进程结束也没事。本着一次编写,多次使用的原则,专门设计了一个帮助类来专职这类委托的异步调用。帮助类的代码如下:
  public class EventHelper {
  public static void UnsafeBeginInvoke(Delegate del,params object[] args){
  AsyncFire asyncFire = InvokeDelegate;
  asyncFire.BeginInvoke(del, args, ThrowCallback, asyncFire);
  }
  delegate void AsyncFire(Delegate del,object[] args);
  static void InvokeDelegate(Delegate del,object[] args){
  del.DynamicInvoke(args);
  }
  static void ThrowCallback(IAsyncResult ar) {
  AsyncFire asyncFire = ar.AsyncState as AsyncFire;
  asyncFire.EndInvoke(ar);
  }
  }
  核心实现是将委托的调用封装起来,在另外一个委托中去调用,然后对另外的那个委托用EndInvoke来释放可能的异常,这样就能够发现单纯的调用BeginInvoke后委托执行时引发的异常。这样修改后,刚才的代码就可以这样来调用托福答案
  EmployeeCollection data = new EmployeeCollection();
  data.Loaded += data_Loaded;
  Action<EmployeeCollection> action = (d) => {
  DalHelper.Fill(data);
  data.RaiseEventLoaded();
  };
  EventHelper.UnsafeBeginInvoke(action, data);
  代码还如最初的设计那么简单,而且真要是委托中发生了异常,也能够发现这个错误,而不是让这个错误被掩盖。
  另外,刚才的实现不是类型安全的,类型安全可以通过重载来解决,例子如下:
  public class EventHelper {
  public static void UnsafeBeginInvoke(Delegate del,params object[] args){
  AsyncFire asyncFire = InvokeDelegate;
  asyncFire.BeginInvoke(del, args, ThrowCallback, asyncFire);
  }
  delegate void AsyncFire(Delegate del,object[] args);
  static void InvokeDelegate(Delegate del,object[] args){
  del.DynamicInvoke(args);
  }
  static void ThrowCallback(IAsyncResult ar) {
  AsyncFire asyncFire = ar.AsyncState as AsyncFire;
  asyncFire.EndInvoke(ar);
  }
  #region 添加类型安全的委托
  public static void BeginInvoke(Action del){
  UnsafeBeginInvoke(del);
  }
  public static void BeginInvoke<T,U>(Action<T,U> del,T t, U u){
  UnsafeBeginInvoke(del,t,u);
  }
  public static void BeginInvoke<T,U,V>(Action<T,U> del,T t, U u, V v){
  UnsafeBeginInvoke(del,t,u,v);
  }
  #endregion 添加类型安全的委托
  }
  
  可以根据自己的需要添加类型安全的实现雅思答案

委托异步调用时BeginInvoke的陷阱处理的更多相关文章

  1. 通过委托来实现异步 Delegate的BeginInvoke和EndInvoke

    什么是.net的异步机制呢? 解释这个话题之前,先让我们来看看同步执行的程序 https://github.com/chucklu/Test/blob/master/DotNet4.5开发指南/并行处 ...

  2. C#如何使用异步编程【BeginInvoke/EndInvoke】

    怎么使用异步,就是用委托进行处理,如果委托对象在调用列表中只有一个方法,它就可以异步执行这个方法.委托类有两个方法,叫做BeginInvoke和EndInvoke,它们是用来异步执行使用. 异步有三种 ...

  3. MVC+Spring.NET+NHibernate .NET SSH框架整合 C# 委托异步 和 async /await 两种实现的异步 如何消除点击按钮时周围出现的白线? Linq中 AsQueryable(), AsEnumerable()和ToList()的区别和用法

    MVC+Spring.NET+NHibernate .NET SSH框架整合   在JAVA中,SSH框架可谓是无人不晓,就和.NET中的MVC框架一样普及.作为一个初学者,可以感受到.NET出了MV ...

  4. 异步和多线程,委托异步调用,Thread,ThreadPool,Task,Parallel,CancellationTokenSource

    1 进程-线程-多线程,同步和异步2 异步使用和回调3 异步参数4 异步等待5 异步返回值 5 多线程的特点:不卡主线程.速度快.无序性7 thread:线程等待,回调,前台线程/后台线程, 8 th ...

  5. C#的dll被其他程序调用时,获取此dll正确的物理路径

    当C# dll被其他程序调用时,用Application.StartupPath获取的dll路径并不一定是此dll的物理路径,有可能是调用程序的路径. 以下方法或者能够获取dll正确的物理路径(未经过 ...

  6. 解决SpringCloud使用Feign跨服调用时header请求头中的信息丢失

    在使用SpringCloud进行Feign跨服调用时header请求头中的信息会丢失,是因为Feign是不会带上当前请求的Cookie信息和头信息的,这个时候就需要重写请求拦截. 1.需要重写Requ ...

  7. C#委托异步调用

    参考页面: http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html http://www.yuanjiaocheng.net/w ...

  8. C#_delegate - 异步调用实例 BeginInvoke EndInvoke event

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  9. 委托-异步调用-泛型委托-匿名方法-Lambda表达式-事件【转】

    1. 委托 From: http://www.cnblogs.com/daxnet/archive/2008/11/08/1687014.html 类是对象的抽象,而委托则可以看成是函数的抽象.一个委 ...

随机推荐

  1. Hibernate配置文件中hiberante.hbm2ddl.auto四个参数的配置

    我们在搭建环境的时候,在配置文件中有一个属性标签为: <property name="hibernate.hbm2ddl.auto">     </propert ...

  2. 《A First Course in Probability》-chaper8-极限定理-切比雪夫不等式

    基于对概率问题的抽象化,通过期望.方差.随机变量X及其概率,我们想要通过几个量推出另外几个量的特征,笼统的来说,极限定理起到的作用便在于此 切比雪夫不等式: 在证明切比雪夫不等式之前,我们先要完成对马 ...

  3. denyhost

    1. denyhost 简介及ssh安全 对外提供的服务器,每天都会被恶意扫描,试图暴力穷举密码,达到入侵的目的.从而控***务器,占用资源.网页挂马.垃圾广告.更会影响我们业务的正常使用和数据的安全 ...

  4. poj2007

    极角排序,其实是叉乘排序 #include <iostream> #include <algorithm> #include <math.h> #include & ...

  5. mysql 循环插入100w

    use md5db; DROP PROCEDURE if exists myFunction; delimiter $$ CREATE PROCEDURE myFunction() BEGIN DEC ...

  6. linux防火墙 基础知识

    转 http://drops.wooyun.org/tips/1424 iptables介绍 linux的包过滤功能,即linux防火墙,它由netfilter 和 iptables 两个组件组成. ...

  7. 常用的Linux操作一

    Linux 常用的操作必须明白. 1.ls  和ll 列出文件的目录. 2.tail -f XXX  查看文件. 3.chmod -R 777 XXX.jar 赋予权限 4.cat 查看文件 -n 对 ...

  8. 【转】仿Android 联系人SideBar排序,根据拼音A-Z字母快速导航,以及输入搜索条件过滤,显示姓名的文字图片

    1.首先我们把这几个工具类拷贝到自己的项目中,这些都是很常见的类: CharacterParser       –这是用来把中文转成拼音的工具类 PinyinComparator   –拼音首字母的比 ...

  9. ios使用openUrl进行应用跳转

    1.拨打电话: [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://68979"]]; ...

  10. Monitor and diagnose performance in Java SE 6--转载

    Java SE 6 provides an in-depth focus on performance, offering expanded tools for managing and monito ...