zoukankan      html  css  js  c++  java
  • C# 5.0功能之Async一瞥

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

     

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

     

    进入正题:

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

     

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

     

    任务:

    建立一个Windows Form应用程序,当点击按钮时,先显示一行字,例如,开始计算什么的,用以表示状态,然后计算从1int.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<
    intlong> 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>。这个返回值其实有三个选项:voidTaskTask<T>,具体怎么用,大家查MSDNC#4.0中的Task类吧。

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

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

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

     

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

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

     

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

    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中已经实现了;多线程的命名空间也早就存在;TaskC# 4.0中被引入……

     

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

     

     

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

  • 相关阅读:
    USACO 1.3 warmhole
    hadoop本地库与系统版本不一致引起的错误解决方法
    hadoop安装遇到的各种异常及解决办法
    Hadoop学习笔记【分布式文件系统学习笔记】
    Hadoop学习笔记【Hadoop家族成员概述】
    Ext2.x学习笔记
    Memcached学习笔记
    关于反向生成url
    python 练习题- 图书租金计算
    python 练习题- letcode 168. Excel表列名称
  • 原文地址:https://www.cnblogs.com/linlf03/p/2391454.html
Copyright © 2011-2022 走看看