委托异步调用时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 类是对象的抽象,而委托则可以看成是函数的抽象.一个委 ...
随机推荐
- QTP自传之测试报告
前言 测试报告是测试阶段的最后产出,也是最重要的产出,自动化测试报告也是如此.前期所做的工作,添加对象.编写脚本等都是为了可以生成一份正确.严谨的测试报告.我作为一款功能全面的自动化测试工具,毫无疑问 ...
- bzoj 1602 [Usaco2008 Oct]牧场行走(LCA模板)
1602: [Usaco2008 Oct]牧场行走 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 379 Solved: 216[Submit][Sta ...
- [Java] JavaMail 简单案例
网易提供了免费的 SMTP / POP3服务,可用于编程测试,详情见 什么是POP3.SMTP和IMAP? 只需要拥有一个网易邮箱账号,并开启该账号的 SMTP / POP3 功能,便可以通过程序发送 ...
- <离散数学>学习笔记1--逻辑和证明
今天开始离散数学的自学旅程. 主题:逻辑和证明 逻辑规则给出数学语句的准确含义.逻辑对计算机科学有着重要作用.为了理解数学,我么必须理解正确的数学论证是由什么组成的.只要证明一个数学语句是真的,我们就 ...
- Git全解析之用起来先
文章目录 1. Git全解析之用起来先 1.1. 先安装Git环境 1.2. 配置 1.3. 简单了解Git 1.3.1. Git对象模型 SHA 1.3.2. Git目录与工作目录 1.4. 可以开 ...
- Double与BigDecimal 比较
1] 精确的浮点运算: 在Java里面,有时候为了保证数值的准确性需要精确的数据,先提供一个例子就可以发现问题了: public class FloatNumberTester { public st ...
- Solr多核的配置
Solr 多核(MultiCore)配置 Solr Multicore意义 Solr Multicore 是 solr 1.3 的新特性.其目的一个solr实例,可以有多个搜索应用.< xmln ...
- 从Delphi 7升级到Delphi XE
Delphi 7和XE中间有好几个版本号,可都不太流行,一是由于Delphi有些边缘化,二是7在XP环境下是近乎完美的版本号.市场上关于delphi的书越来越少,提供从7升级到XE介绍的资料差点儿没用 ...
- sparkSQL1.1入门之二:sparkSQL执行架构
在介绍sparkSQL之前.我们首先来看看,传统的关系型数据库是怎么执行的.当我们提交了一个非常easy的查询: SELECT a1,a2,a3 FROM tableA Where con ...
- 查看Linux声卡基本信息[转载]
查看系统版本~$ uname -aLinux laptop 2.6.27-7-generic #1 SMP Tue Nov 4 19:33:20 UTC 2008 i686 GNU/Linux 查看型 ...