委托异步调用时BeginInvoke的陷阱处理
这个陷阱来自于一个需求:需要异步在后台处理数据,处理完后触发处理完成的事件,大概是这么写的:
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的陷阱处理的更多相关文章
- 通过委托来实现异步 Delegate的BeginInvoke和EndInvoke
什么是.net的异步机制呢? 解释这个话题之前,先让我们来看看同步执行的程序 https://github.com/chucklu/Test/blob/master/DotNet4.5开发指南/并行处 ...
- C#如何使用异步编程【BeginInvoke/EndInvoke】
怎么使用异步,就是用委托进行处理,如果委托对象在调用列表中只有一个方法,它就可以异步执行这个方法.委托类有两个方法,叫做BeginInvoke和EndInvoke,它们是用来异步执行使用. 异步有三种 ...
- 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 ...
- 异步和多线程,委托异步调用,Thread,ThreadPool,Task,Parallel,CancellationTokenSource
1 进程-线程-多线程,同步和异步2 异步使用和回调3 异步参数4 异步等待5 异步返回值 5 多线程的特点:不卡主线程.速度快.无序性7 thread:线程等待,回调,前台线程/后台线程, 8 th ...
- C#的dll被其他程序调用时,获取此dll正确的物理路径
当C# dll被其他程序调用时,用Application.StartupPath获取的dll路径并不一定是此dll的物理路径,有可能是调用程序的路径. 以下方法或者能够获取dll正确的物理路径(未经过 ...
- 解决SpringCloud使用Feign跨服调用时header请求头中的信息丢失
在使用SpringCloud进行Feign跨服调用时header请求头中的信息会丢失,是因为Feign是不会带上当前请求的Cookie信息和头信息的,这个时候就需要重写请求拦截. 1.需要重写Requ ...
- C#委托异步调用
参考页面: http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html http://www.yuanjiaocheng.net/w ...
- C#_delegate - 异步调用实例 BeginInvoke EndInvoke event
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 委托-异步调用-泛型委托-匿名方法-Lambda表达式-事件【转】
1. 委托 From: http://www.cnblogs.com/daxnet/archive/2008/11/08/1687014.html 类是对象的抽象,而委托则可以看成是函数的抽象.一个委 ...
随机推荐
- centos升级openssh的两种方式
此文介绍的是服务器在有网络和无网络情况下升级openssh方式. 一.首先介绍一个无网络如何升级: 1.准备相关的包 openssh下载地址: http://mirror.internode.on. ...
- bzoj 1602 [Usaco2008 Oct]牧场行走(LCA模板)
1602: [Usaco2008 Oct]牧场行走 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 379 Solved: 216[Submit][Sta ...
- [Locked] Generalized Abbreviation
Write a function to generate the generalized abbreviations of a word. Example:Given word = "wor ...
- java 编辑报错 非法字符: \ufeff 解决方案
用Notepad ++ 调成utf-8 格式 bom 或无bom根据情况 新建类 把代码一句句粘进去 ok
- Scrapy:Python的爬虫框架
网络爬虫,是在网上进行数据抓取的程序,使用它能够抓取特定网页的HTML数据.虽然我们利用一些库开发一个爬虫程序,但是使用框架可以大大提高效率,缩短开发时间.Scrapy是一个使用Python编写的,轻 ...
- RabbitMQ-死信(Dead Letter)
对于有异常的消息我们可以有如下做法: 记录下来再ack. nack或者reject,同时将requeue设为false. 在第2条的基础上增加死信(Dead Letter). 上边的第3个做法可以 ...
- C#的dictionary使用总结
Dictionary<string, string>是一个泛型,本身有集合的功能有时候可以把它看成数组. 他的结构是这样的:Dictionary<[key], [value]> ...
- Windows Minifilter驱动 - 调式 (4)
写不论什么程序动态调试是很重要的.驱动开发也不例外. 通常如今写驱动的时候,都是在VM上跑的,调试手段基本也是本地windbg + 虚拟机. 虚拟机配置 我用的是win7, 第一步,看以下.成功运行后 ...
- yii自动登陆的验证机制浅析
一直在使用yii进行开发, 也知道如何去使用, 也仅仅是知道怎么去用罢了, 终归是没研究过源码, 心里发虚, 今天遇到一个问题, 关于自动登陆的问题. 要求就是, 修改登陆保存session天数为自定 ...
- SPOJ 181 - Scuba diver 二维背包
潜水员要潜水,给出n个气缸(1<=n<=1000),每个气缸中有氧气量为ti,氮气量为ai,气缸重量为wi(1<=ti<=21,1<=ai<=79,1<=wi ...