这个陷阱来自于一个需求:需要异步在后台处理数据,处理完后触发处理完成的事件,大概是这么写的:
  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. 在Ubuntu中安装Redis

    原文地址:http://blog.fens.me/linux-redis-install/ 在Ubuntu中安装Redis R利剑NoSQL系列文章,主要介绍通过R语言连接使用nosql数据库.涉及的 ...

  2. firefox HackBar组件模拟请求POST请求

    组件下载地址:https://addons.mozilla.org/zh-CN/firefox/addon/hackbar/

  3. 【递推】地铁重组(subway) 解题报告

    问题来源 BYVoid魔兽世界模拟赛 [问题描述] 蒙提在暴风城与铁炉堡之间的地铁站中工作了许多年,除了每天抓一些矿道老鼠外,没有其他的变化.然而最近地铁站终于要扩建了,因为侏儒们攻克了建设长距离穿海 ...

  4. libvirt基于安装

  5. Threading Module源码概述(三)

    Threading中的Thread threading中一个关键的组件是threading.Thread. class Thread(_Verbose): __initialized = False ...

  6. angularJS 指令一

    指令1.指令本质上就是AngularJS拓展具有自定义功能的HTML元素的途径.通过自定义元素来创建指令,如:<my-directive></my-directive>.dir ...

  7. codevs1955光纤通信(并查集)

    /* 第一眼以为就是个区间覆盖 然后敲完提交60分0.0 然而觉得自己的做法很对 以为数据错了 后来发现XXX他的牛棚是一圈(牛过得挺好的啊 还能赏湖...) 然后枚举断开的点 可惜n=750 p=1 ...

  8. UWP app HelloWorld 的创建

    步骤 1:在 Visual Studio 中创建新项目 启动 Visual Studio 2015 RC.将出现 Visual Studio 2015 RC 起始页. (从现在开始,我们将 Visua ...

  9. 【开源java游戏框架libgdx专题】-05-模块描述与上下文

    模块描述(Modules overview) Input:为所有的平台提供一个统一的输入模型和处理程序. 获取触摸示例: if (Gdx.input.isTouched()) { System.out ...

  10. CSS从大图中抠取小图完整教程(background-position应用) (转)

    自认为把background-position的应用讲得非常通俗易懂的教材.做个记号. 相信很多喜欢研究网页界面的童鞋都遇到过一个奇妙的现象:网页中很多图片素材被合成在一张图片上. 起初小菜模仿网站的 ...