C# 5.0功能之Async一瞥

原文:

http://www.cnblogs.com/xiaomi7732/archive/2011/06/27/AsyncDemo.html

 

距离微软发布 Async CTP 已经有个把月了吧,周围大家都在热议着 Async 。如果你对 Async 已经非常熟悉,那么,请直接略过……如果你跟我一样,只会一点点异步编程,但又觉得以前的异步编程比较麻烦,那么,让我们一起来探索一下下一代的 C# 会给我们带来什么。( Async CTP 同样对 VB 有支持的。)

 

本文的例子基于 Async CTP SP1 Refresh 完成。由于 Async 还处于 CTP 阶段,很多东西还在讨论,因此,也许待到 C# 5.0 发布的时候,细节还会变动。但是,大体的思路,概念应该是不会有什么变化了。

 

进入正题:

首先,要试用 Async 功能,我们需要安装 Visual Studio 2010 SP1 Microsoft Visual Studio Async CTP (SP1 Refresh)

 

我们首先设定一个简单的任务,分别来看一下,同步编程,利用回调进步异步编程和 Async 编程的方法,然后来通过他们来分析一下, Async 到底是什么,它给我们带来了什么。

 

任务:

建立一个 Windows Form 应用程序,当点击按钮时,先显示一行字,例如,开始计算什么的,用以表示状态,然后计算从 1 int.Max/2 的累加,并把结果显示出来。

 

同步我们会这么做:

首先,写一个函数来实现基本算法:

        #region  Do things
        
public  long  DoSomething( int  n)
        {
            
long  result = 1;
            
for  ( int  i = 1; i <= n; i++)
            {
                result += i;
            }
            
return  result;
        }
        #endregion

然后,添加一个按钮的 Click 事件处理程序:

         private  void  btnSync_Click( object  sender,  EventArgs  e)
        {
            lblResult.Text = 
"Start to do something . . ." ;
            
long  value = DoSomething( int .MaxValue / 2);
            lblResult.Text = value.ToString();
        }

代码第一行改写 Label 的字样;第二行调用算法获得结果;第三行把结果输出。看似挺不算的。运行一下,就会发现有两个问题:

  1. 这个算法需要四五秒钟左右的实现时间,并且在这几秒钟的时间里,界面是锁死的,也就是说应用程序就像死了一样,它不接受任何用户操作。(也许我的电脑比较差,呵呵,所以,如果你没有遇到这种情况,请加大输入参数的值,让它算一会儿。)
  1. 我们没有看到 Start to do something 这一行字。

 

OK ,出现这个现象也是可以理解的,因为我们把大量的运算添加到了 UI 线程里面了。所以,解决方法就是把它放到外面。我试了一下不用 Async ,实现的代码如下:

         private  void  btnCallback_Click( object  sender,  EventArgs  e)
        {
            lblResult.Text = 
"Start to do something . . ." ;
            Func<
int long > callBackDelegate =  this .DoSomething;
            callBackDelegate.BeginInvoke(
                
int .MaxValue / 2,
                
new  AsyncCallback(
                a =>
                {
                    lblResult.Invoke(
new  MethodInvoker(() =>
                        {
                            lblResult.Text = callBackDelegate.EndInvoke(a).ToString();
                        }));
                }),
                
null );
        }

如果你觉得这段代码比较晕,那就跳过这一节吧。可能我代码写得不好,大家将就看我简单解释一下,我首先给 DoSomething 写了一个代理,然后,调用了代理的 BeginInvoke 方法,把算法放到了其它的 Thread 中去调用了。这个代理执行完了以后,因为它不会直接返回一个 long 型的值,而是会去执行一个 AsyncCallBack ,所以,就在这个 Callback 里,去调用这个代理的 EndInvoke()

 

好吧,且不论代码质量,这个就是有 Async 之前的一种实现异步的方法。

从这个代码里,我们完全看不到原来代码的影子,我也没有办法像解释同步代码一样解释:第一、第二、第三……有了 Async 之后呢?呵呵,代码说明一切:

         public  Task < long > DoSomethingAsync( int  n)
        {
           
return  TaskEx .Run< long >(() => DoSomething(n));
        }
 
         private  async  void  btnAsync_Click( object  sender,  EventArgs  e)
        {
            lblResult.Text = 
"Start do something..." ;
            
var  x =  await  DoSomethingAsync( int .MaxValue / 2);
            lblResult.Text = x.ToString();
        }

三件事:

第一:添加文件引用: AsyncCtpLibrary.dll 。相信 Async 正式发布之后,这个会出现在 .NET 应用程序集里。

第二:把 DoSomething 封装成一个 Task

第三:添加一些关键字,例如 async ,例如 await

 

我们来仔细看一下代码:

首先,我把要异步执行的代码的返回值写成 Task<T> 。这个返回值其实有三个选项: void Task Task<T> ,具体怎么用,大家查 MSDN C#4.0 中的 Task 类吧。

然后,我调用了 TaskEx 中的 Run<long> 方法,传递给它一个返回值为 long 的方法——就是我们的任务的算法啦。

如果你有兴趣研究,可以看一下 Run<T> 其实调用了 Task.Factory.StartNew<T> ,而这个 Start<New> 则是先建了一个 Task ,然后调用了它的 Start 方法……

好,把算法封成任务部分完成。

 

第二部分代码比较容易解释了:

第一行改写 Label 的字样;第二行调用算法获得结果;第三行把结果输出。 <-- 本行复制 / 粘贴自前文 :-)

 

呵呵,让我们看看细一点,比较一下 Sync Async 的代码:

Sync

Async

         private  void  btnSync_Click( object  sender,  EventArgs  e)
        {
            lblResult.Text = 
"Start to do something . . ." ;
            
long  value = DoSomething( int .MaxValue / 2);
            lblResult.Text = value.ToString();
        }

         private  async  void  btnAsync_Click( object  sender,  EventArgs  e)
        {
            lblResult.Text = 
"Start do something..." ;
            
var  x =  await  DoSomethingAsync( int .MaxValue / 2);
            lblResult.Text = x.ToString();
        }

首先,我们在方法名上加上 async 修饰,声明这是一个有异步调用的方法;

然后,我们在返回 Task<T> 的函数调用( DoSomethingAsync )之前添加一个 await 关键字。来猜猜看 x 是什么类型的?答案是 long 型。有了 await 之后,即使在设计时,编译器会自动把 Task<T> 的类型,转换成 T 类型。

 

代码到这里结束了,但是,新的 Async 功能给我们带来了什么?是异步编程的能力吗?我们用 Callback 同样可以实现异步,而 IAsyncCallback 接口应该在 .NET 1.1 中已经实现了;多线程的命名空间也早就存在; Task C# 4.0 中被引入……

 

我想, Async 给程序员带来的是一种代码逻辑为中心并且实现多线程编程的方式。通过最后的比较,我们看到, Async 的代码与 Sync 的代码相差无几,程序不再需要花大量精力去考虑回调、同步等等的问题……这与 C# 一直在努力的方向是一致的,程序员更多的来描述是什么而不是怎么做。

 

最后,附上应用程序下载和源代码,还有运行界面截图……(好吧,我不是美工,请原谅 :-)

点击下载源代码

 

点击 Async ,看到运行提示:


 

显示执行结果:

最新最官方的Async资料在这儿:^v^

 http://msdn.microsoft.com/Async

Little knowledge is dangerous.

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值