好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

.NET4.5之初识async与await

.NET4.5之初识async与await

.NET4.5之初识async与await

本人是从.NET4.0刚出的时候接触的.NET环境,所以学的东西就是4.0及其之前的。时代飞速前进,目测5.0也快出了吧,但一直也没去接受新的技术。最近由于要学习Web API,快看完了,却发现4.5已经大行其道了,于是又进行补脑。async与await便是其中之一:

  这是两个关键字,用于异步编程。我们传统的异步编程方式一般是Thread、ThreadPool、BeginXXX、EndXXX等等。把调用、回调分开来,代码的逻辑是有跳跃的,于是会导致思路不是很清晰的问题,在.NET 4.5中,新推出的async、await关键字,可以帮助我们像写同步方法一样去写异步方法(保证代码的整齐清晰)。

  先来看个传统同步方法例子:  

  1           static   void  Main( string  [] args)
   2           {
   3               //   同步方式 
  4              Console.WriteLine( "  同步方式测试开始!  "  );
   5              SyncMethod( 0  );
   6              Console.WriteLine( "  同步方式结束!  "  );
   7               Console.ReadKey();
   8           }
   9  
 10           //   同步操作 
 11           private   static   void  SyncMethod( int   input)
  12           {
  13              Console.WriteLine( "  进入同步操作!  "  );
  14               var  result =  SyancWork(input);
  15              Console.WriteLine( "  最终结果{0}  "  , result);
  16              Console.WriteLine( "  退出同步操作!  "  );
  17           }
  18  
 19           //   模拟耗时操作(同步方法)  
 20           private   static   int  SyancWork( int   val)
  21           {
  22               for  ( int  i =  0 ; i <  5 ; ++ i)
  23               {
  24                  Console.WriteLine( "  耗时操作{0}  "  , i);
  25                  Thread.Sleep( 100  );
  26                  val++ ;
  27               }
  28               return   val;
  29          }

  可以从右图中看到执行结果,是非常典型的同步执行方法。

  async关键字能用在方法、lambda表达式的声明部分,用来标示此方法可能包含await关键字,只有拥有async才能在其内部使用await关键字。 异步方法可以具有 Task、Task<>或void的返回类型; await关键字则是用于返回值是“可等待”类型(awaitable)的方法或lambda表达式内, “awaitable” 可以是任何类型(常见的有Task、Task<>),它必须公开一个 GetAwaiter()  方法并且返回有效的 ”awaiter” 。更详细的信息可以参考“ 关于Async与Await的FAQ ”,里面介绍了这些概念与注意事项。

  当一个async方法,且内部包含await关键字,它就会在编译的时候成为一个异步方法,如果没有await关键字,则它将只会被当成一个同步方法来执行。如果对其内部实现感兴趣可以参考“ 异步性能:了解 Async 和 Await 的成本 ”一文,相信对深入了解这种机制还是有所帮助的。

  现在我们尝试使用新出的异步关键字async、await来改造成异步调用:

         static   void  Main( string  [] args)
        {
              //   异步方式 
            Console.WriteLine( "  \n异步方式测试开始!  "  );
            AsyncMethod(  0  );
            Console.WriteLine(  "  异步方式结束!  "  );
            Console.ReadKey(); 
        }  

          //   异步操作 
         private   static   async   void  AsyncMethod( int   input)
        {
            Console.WriteLine(  "  进入异步操作!  "  );
              var  result =  await   AsyncWork(input);
            Console.WriteLine(  "  最终结果{0}  "  , result);
            Console.WriteLine(  "  退出异步操作!  "  );
        }

          //   模拟耗时操作(异步方法)  
         private   static   async  Task< int > AsyncWork( int   val)
        {
              for  ( int  i =  0 ; i <  5 ; ++ i)
            {
                Console.WriteLine(  "  耗时操作{0}  "  , i);
                  await  Task.Delay( 100  );
                val ++ ;
            }
              return   val;
        } 

   先来看结果吧,我们发现耗时操作已经是异步进行了。整体流程大概是先由Main函数异步调用AsyncMethod,并不等待AsyncMethod完成,继续往下执行。而AsyncMethod方式在被调用后,在分配到时间片时开始启动,执行函数体内容,并由于await AsyncWork语句而继续异步调用AsyncWork,但由于await关键字,将在此等待AsyncWork完成后,再继续往下执行。那么,AyncWork也一样的,被调用后,在分配到时间片时开始启动,执行耗时操作。

  可以看到,使用了新的关键字后,同步与异步编程的语法差别进一步减少。随着.NET 4.5的推出,许多新类库和既有类库都支持这种新型的异步语法(比如HttpClient、HttpServer、MemoryStream...),它们以类似ReadAsync、WriteAsync、SendAsync等分开方法来提供具有async声明,且返回类型为Task、Task<>的异步工作方式。

   补充:

  刚才有朋友提到await Task.Delay(100)这条语句,这是为了让AsyncWork成为异步方法才加的,如果你要进行的操作不支持await修饰怎么办,其实很简单,使用Task.Factory.StartNew()就行了,举例:

  1           //   异步操作 
  2           private   static   async   void  AsyncMethod( int   input)
   3           {
   4              Console.WriteLine( "  进入异步操作!  "  );
   5               var  result =  await  Task.Factory.StartNew((Func< object ,  int > )SyncWork2, input);
   6              Console.WriteLine( "  最终结果{0}  "  , result);
   7              Console.WriteLine( "  退出异步操作!  "  );
   8           }
   9  
 10           //   模拟耗时操作(同步方法) 
 11           private   static   int  SyncWork2( object   input)
  12           {
  13               int  val = ( int  )input;
  14               for  ( int  i =  0 ; i <  5 ; ++ i)
  15               {
  16                  Console.WriteLine( "  耗时操作{0}  "  , i);
  17                  Thread.Sleep( 100  );
  18                  val++ ;
  19               }
  20               return   val;
  21          }

  这样,我们的SyncWork2实际上却是异步执行的,所得结果与前面的异步方法一致,只是这样一来输入参数只能是object类型,需要进行类型转化。另外,除了StartNew,我们还可以新建一个Task,然后调用Run,以完成同样效果,且此时的输入参数就是强类型的了。

  目前来说,这种异步工作还是会造成本人使用上的不适,不过如果在将来的版本中,继续推广使用,相信不久便能熟练,且加快写代码的速度,编写出逻辑清晰的代码。

转载请注明原址: http://www.cnblogs.com/lekko/archive/2013/03/05/2944282.html  

 

分类:  .NET

标签:  .NET

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于.NET4.5之初识async与await的详细内容...

  阅读:41次