异步编程模型--使用 IAsyncResult 对象

先推荐阅读下面的资料:

MSDN:异步编程设计模式

IBM developerworks: 使用异步 I/O 大大提高应用程序的性能

参考博文:

 

1、正确使用异步操作 

2、Lab:体会ASP.NET异步处理请求的效果

3、WCF中的异步调用

4、WCF从理论到实践(11)-异步

5、异步编程

 

.NET Framework 为异步操作提供两种设计模式:
1、使用 IAsyncResult 对象的异步操作。
2、使用事件的异步操作。

IAsyncResult接口类型

 

    [ComVisible( true )]
    
public   interface  IAsyncResult
    {
        
//  摘要:
        
//      获取用户定义的对象,它限定或包含关于异步操作的信息。
        
//
        
//  返回结果:
        
//      用户定义的对象,它限定或包含关于异步操作的信息。
         object  AsyncState {  get ; }
        
//
        
//  摘要:
        
//      获取用于等待异步操作完成的 System.Threading.WaitHandle。
        
//
        
//  返回结果:
        
//      用于等待异步操作完成的 System.Threading.WaitHandle。
        WaitHandle AsyncWaitHandle {  get ; }
        
//
        
//  摘要:
        
//      获取异步操作是否同步完成的指示。
        
//
        
//  返回结果:
        
//      如果异步操作同步完成,则为 true;否则为 false。
         bool  CompletedSynchronously {  get ; }
        
//
        
//  摘要:
        
//      获取异步操作是否已完成的指示。
        
//
        
//  返回结果:
        
//      如果操作完成则为 true,否则为 false。
         bool  IsCompleted {  get ; }
    }

 

下面是使用 IAsyncResult 对象的测试代码。

  public   delegate   string  AsyncDelegate( int  callDuration,  out   int  threadId);
    
class  Program
    {
        
static   void  Main( string [] args)
        {
            Fun1();
            Console.ReadLine();
        }

        
private   static   int  threadId;

        
// 阻塞等待   使用 EndInvoke 等待异步调用  
         static   void  Fun1()
        {
            
// 创建示例类的实例。
            AsyncDemo ad  =   new  AsyncDemo();
            
//  创建委托
            AsyncDelegate dlgt  =   new  AsyncDelegate(ad.TestMethod);
            
//  委托在这里开始异步调用。
            IAsyncResult ar  =  dlgt.BeginInvoke( 5000 , out  threadId,  null null );
            
// 人为的线程阻塞。
            Thread.Sleep( 0 );
            Console.WriteLine(
" 主线程 {0}开始工作 " ,Thread.CurrentThread.ManagedThreadId);
            
//  委托开始EndInvoke调用,这个过程会使主线程等待异步调用完成并返回结果。
             string  ret  =  dlgt.EndInvoke( out  threadId, ar);
            Console.WriteLine(
" 异步线程 {0},返回值 / " { 1 }/ " . " , threadId, ret);
            Console.WriteLine(
" 主线程{0}结束工作 " , Thread.CurrentThread.ManagedThreadId);
        }
        
        
// 阻塞等待  使用 WaitHandle 等待异步调用
         static   void  Fun2()
        {
            AsyncDemo ad 
=   new  AsyncDemo();
            AsyncDelegate dlgt 
=   new  AsyncDelegate(ad.TestMethod);
            IAsyncResult ar 
=  dlgt.BeginInvoke( 5000 , out  threadId,  null null );
            Thread.Sleep(
0 );
            Console.WriteLine(
" 主线程 {0}开始工作 " , Thread.CurrentThread.ManagedThreadId);
            
// 主线程在这里等待,直到异步线程执行完。
            ar.AsyncWaitHandle.WaitOne();
            
//  和前一方案的区别在于,你可以在异步调用完成后,获取异步调用返回值之前
            
// 在这里做点任何你想作的事。
            
// 调用EndInvoke获取异步调用的返回结果.
             string  ret  =  dlgt.EndInvoke( out  threadId, ar);
            Console.WriteLine(
" 异步线程 {0},返回值 / " { 1 }/ " . " , threadId, ret);
            Console.WriteLine(
" 主线程{0}结束工作 " , Thread.CurrentThread.ManagedThreadId);
        }

        
// 轮询状态    轮询异步调用完成
         static   void  Fun3()
        {
            AsyncDemo ad 
=   new  AsyncDemo();
            AsyncDelegate dlgt 
=   new  AsyncDelegate(ad.TestMethod);
            IAsyncResult ar 
=  dlgt.BeginInvoke( 5000 , out  threadId,  null null );
            Console.WriteLine(
" 主线程 {0}开始工作 " , Thread.CurrentThread.ManagedThreadId);
            
// 这里每隔10毫秒就检测(轮询)一下异步执行的状态,
            
// 直到异步调用完成,IsCompleted的值变为ture为止。
             while  (ar.IsCompleted  ==   false )
            {
                Thread.Sleep(
10 );
            }

            
// 还记得微软的那个善意的提醒吗?虽然IsCompleted为true了,
            
// 我们还是调用一下EndInvoke,来获取返回值。
             string  ret  =  dlgt.EndInvoke( out  threadId, ar);
            Console.WriteLine(
" 异步线程 {0},返回值 / " { 1 }/ " . " , threadId, ret);
            Console.WriteLine(
" 主线程{0}结束工作 " , Thread.CurrentThread.ManagedThreadId);
        }

        
// 通知机制    异步调用完成时执行回调方法
         static   void  Fun4()
        {
            AsyncDemo ad 
=   new  AsyncDemo();
            AsyncDelegate dlgt 
=   new  AsyncDelegate(ad.TestMethod);
            
// 注意第三个参数,这就是我们要用到的回调方法。
            
// 第四个参数更为有趣,它可以是任何Object对象,这里它就是
            
// 执行异步调用的委托本身,把委托本身传递进去的原因在下面可以看到。
            Console.WriteLine( " 主线程 {0}开始工作 " , Thread.CurrentThread.ManagedThreadId);
            IAsyncResult ar 
=  dlgt.BeginInvoke( 5000 , out  threadId,  new  AsyncCallback(CallbackMethod), dlgt);
            Console.WriteLine(
" 主线程 {0}结束工作 " , Thread.CurrentThread.ManagedThreadId);
            Console.ReadLine();
        }
        
// 回调函数必须严格的遵照AsyncCallback委托的签名。
         static   void  CallbackMethod(IAsyncResult ar)
        {
            
// 在这里,上面那个dlgt作为参数的作用得到了体现,原来它就是为了完成对EndInvoke的调用啊。
            AsyncDelegate dlgt  =  (AsyncDelegate)ar.AsyncState;
            
// 通过对EndInvoke的调用获取返回值。
             string  ret  =  dlgt.EndInvoke( out  threadId, ar);
            Console.WriteLine(
" 异步线程 {0},返回值 / " { 1 }/ " . " , threadId, ret);
        }
    }
    
// 使用异步编程模型 
     public   class  AsyncDemo
    {
        
public   string  TestMethod( int  callDuration,  out   int  threadId)
        {
            Console.WriteLine(
" 异步方法开始工作 " );
            Thread.Sleep(callDuration);
            threadId 
=  Thread.CurrentThread.ManagedThreadId; 
            
return   " 异步方法执行时间  "   +  callDuration.ToString();
        }
    }

 执行结果:

Fun1--------------------

异步方法开始工作
主线程 10开始工作
异步线程 7,返回值 "异步方法执行时间 5000".
主线程10结束工作
Fun2---------------------
异步方法开始工作
主线程 10开始工作
异步线程 7,返回值 "异步方法执行时间 5000".
主线程10结束工作
Fun3---------------------

主线程 10开始工作
异步方法开始工作
异步线程 7,返回值 "异步方法执行时间 5000".
主线程10结束工作
Fun4---------------------
主线程 10开始工作
主线程 10结束工作
异步方法开始工作
异步线程 7,返回值 "异步方法执行时间 5000".
--------------------------

工作当中有一个调用ActiveMQ的产品,每天大概是上万的消息。压力也不是很大。最近总是出现调用MQ阻塞的情况。负责MQ的同事也没有找到原因。

我是想寻找一个消息队列的代替品。 上面的第四个方法,异步线程不阻塞调用线程,当然调用线程也无需处理调用结果,貌似可以作为一个代替方案。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值