应用框架的设计与实现——.NET平台(7.事件通知服务.委托.异步编程)

7.2.1 委托
取得消息接收者列表  delesobj.GetInvocationList()
调用每个委托目标  deleobj.DynamicInvoke()

Delegate[] delegates  =  allTargets.GetInvocationList();
object []  params   =   {4,3} ;
foreach  (Delegate dg  in  delegates)
{
    
try
    
{
        
int result = (int)dg.DynamicInvoke(params);
        Console.WriteLine(
"result is {0}", result);
    }

    
catch (Exception ex)
    
{
        
// ignore the exception
    }

}


7.2.2 异步编程
异步调用委托  dele.BeginInvoke(p1, p2, p3, p4) // 后两个参数是回调方法相关的,前面是委托方法的参数
委托方法结果的信息  IAsynResult
委托是否执行结束  IAsynResult.IsCompleted
获取委托方法的结果  dele.EndInvoke(IAsynResult)


委托对象有个方法 BeginInvoke() 可以使委托对象以异步方式(新线程内)运行,该方法是编译时编译器为委托对象加入的。
委托对象运行在内部线程池中,内部线程池是什么?
每个应用程序域有一个线程池,默认包含25个线程。当通过 BeginInvoke() 调用委托时,CLR将使用这个线程池处理委托。
如果异步委托太多,超过了线程池中的空闲线程数,CLR会自动让委托排队,当有线程闲置时再处理它们。

CalculationHandler slowAddHandler  =   new  CalculationHandler(math.SlowAdd);
//  异步方式调用方法
IAsynResult ar  =  slowAddHandler.BeginInvoke( 4 3 null null );
//  检查方法是否已经执行完
while  ( ! ar.IsCompleted)
{
    System.Threading.Thread.Sleep(
1000);
}

//  取得方法执行结果
object  slowResult  =  slowAddHandler.EndInvoke(ar);
Console.Write(
" SlowAdd returns  "   +  ( int )slowResult);


如何使用异步调用方法的回调方法?如何使用 BeginInvoke() 方法的后两个参数?
1.BeginInvoke() 方法的倒数第二个参数是委托对象 AsyncCallback() 类型,
1.1当异步委托方法执行完后异步委托会执行回调函数,这样我们“不停的检查异步委托方法是否执行完”的问题也解决了。
1.2委托对象 AsyncCallback() 有一个参数是 IAsynResult 类型的,
1.3当异步委托执行回调函数时会以 BeginInvoke() 返回的 IAsynResult 对象为参数的,
2.同时 BeginInvoke() 的倒数第一个参数会以 IAsynResult.AsyncState 属性的形式出现。

AsyncCallback 委托的定义如下(类库内定义的):
public delegate void AsyncCallback(IAsyncResult asyncResult)


回调方法:
resultObject.AsyncDelegate  取得异步委托
result.AsyncState  BeginInvoke()的最后一个参数

public   void  OnSlowAddComplete(IAsyncResult result)
{
    AsyncResult resultObject 
= (AsyncResult)result;
    
// 取得委托对象
    CalculationHandler completedDelegate = (CalculationHandler)resultObject.AsyncDelegate;
    
// 取得返回值
    int sum = (int)completedDelegate.EndInvoke(result);
    Console.WriteLine(
"the result is " + sum);
    Console.WriteLine(
"the last parameter is " + result.AsyncState.ToString());
}


执行异步委托方法时使用回调方法:
AsyncCallback callback  =   new  AsyncCallback( this .OnSlowAddComplete);
IAsynResult ar 
=  slowAddHandler.BeginInvoke( 4 3 , callback,  " last 参数 " );



当应用的流程需要多个方法都有结果才能继续时,我们必须等每个方法都执行结束。
如何等每个方法都执行结束?
WaitHandle[]  异步委托等待句柄数组
ar1.AsyncWaitHandle
WaitHandle.WaitAll()  阻塞当前线程,直到所有异步委托方法执行完

IAsynResult ar1  =  slowAdd.BeginInvoke( 5 2 null null );
IAsynResult ar2 
=  sub.BeginInvoke( 3 3 null null );
IAsynResult ar3 
=  multiply.BeginInvoke( 4 13 null null );
WaitHandle[] waitArray 
=   {ar1.AsyncWaitHandle, ar2.AsyncWaitHandle, ar3.AsyncWaitHandle} ;
WaitHandle.WaitAll(waitArray);
int  result1  =  slowAdd.EndInvoke(ar1);
int  result2  =  sub.EndInvoke(ar2);
int  result3  =  multiply.EndInvoke(ar3);
Console.Write(result1 
+  result2  +  result3);


异常:
我们不知道异步委托什么时候发生异常,也不能即时处理它。
如果有异常发生了,我们怎么捕获它哪?
如果有异常会在调用 EndInvoke() 方法时抛出

IAsynResult ar1  =  slowAdd.BeginInvoke( 5 2 null null );
WaitHandle.WaitAll(
new  WaitHandle[] {ar1} );
try
{
    
int result1 = slowAdd.EndInvoke(ar1);
}

catch  (Exception ex)
{
    Console.Write(ex.Message);
}
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值