zoukankan      html  css  js  c++  java
  • Future of C# and VB Async, Compiler as a Service

    昨晚抽空看了 PDC 2010 Anders Hejlsberg 的演讲,还是一如既往的激情四溢,每次 Demo 完了之后观众都会发出会心的掌声。


    Anders 在演讲中介绍了 C# 和 VB 接下来的发展方向(讲解是以 C# 进行的,但他说 VB 将会和 C# 同步发展,具备 C# 包含的新特性)。


    演讲的内容包括 Async 和 Compiler as a Service 两部分。

    首先 Anders 着重介绍了 Asnyc. 就是对异步编程的支持。


    我们知道,在 .NET 中,传统的异步编程大致上是通过两种方式来进行的:


    (1) 在发起异步操作的调用中,传入一个回调函数,当异步操作完成后,该函数会被调用到。
    (2) 注册一个事件处理函数,异步操作完成时,会通过引发事件的方式执行到该事件处理函数的代码。


    这两种方式都有很多弱点 - 他们都是二段式的调用。这就意味着我们用常规的写法,无法轻易的安排多个异步操作之间的次序,依赖关系等等。比如,发起两个异步操作 A 和 B,在他们都完成后接着执行异步操作 C. 概念上很简单的事情,但是因为上面说的二段式调用方式的限制,实际编码起来,我们就需要用设定全局标志变量等方式才能达到目的。而且,异常处理、任务取消、timeout 等控制也变得复杂起来。


    在 C# 中,将通过引入两个关键字 asyncawait 来解决这个问题。
    例如以下代码:

    async Task<Movie[]> QueryMoviesAsync(int year, int first, int count) {
    	var client = new WebClient();
    	var url = String.Format(query, year, first, count);
    	var data = await client.DownloadStringTaskAsync(new Uri(url));
    	var movies = 
    		// 用一个 linq 查询从 data 中解析出 movies 对象的集合. 视频比较模糊,这个
    		// 语句就没有详细记下来,这不是重点。
    		from d in data
    		...
    		select xxx;
    		
    	return movies.ToArray();
    }

    其中 async 用于标注一个方法的返回值,用此关键字标注了的方法,其结果不会立即返回,而是返回了一个表示其返回类型的异步操作的承诺。在将来的某个时刻,其中所包含的异步操作完成时,结果才会被陆续返回。

    而 await 关键字,使得线程可以等待一个异步操作完成再继续执行下面的语句。这样,就可以用类似于同步的顺序写法来组织异步代码的次序,完全消除了异步编程的复杂性。

    有了这两个关键字,异常处理、任务取消、timeout 的控制逻辑就可以用常规方法来编写了。

    异常处理只需要用常规的 try..catch 块就可以完成,不必多说。

    任务取消,可以通过向异步方法中传入一个 CancellationTokenSource 对象,然后在适当的时候调用其 Cancel 方法即可。

    而 Timeout 和取消非常类似。代码示例:

    async void StartTimeoutAsync() {
    	await TaskEx.Delay(5000);
    	if (cts != null) {
    		cts.Cancel();
    		statusText.Text = "Cancelled";	
    	}
    }
    
    private void searchButton_Click(object sender, RoutedEventArgs e){
    	// 启动下载任务
    	LoadMoviesAsync(Int32.Parse(textBox.Text));
    	// 启动定时器,执行5秒后取消下载
    	StartTimeoutAsync();
    }

    另一个例子:

    async void ShowDateTimeAsync(){
    	while (true) {
    		Title = "Movie Finder " + DateTime.Now;
    		await TaskEx.Delay(1000);
    	}
    }

    这段代码会在窗体的标题栏上显示当前时间,每秒钟刷新一次。

    上面的代码都没有使用多线程。那么何时该使用多线程呢?当你需要执行计算密集的任务时,多线程才是必要的。简而言之,多线程应该用来充分利用 CPU 资源,而不是用来空置着等待 I/O 任务的完成。

    (Anders: So when do I need more threads? you need threads when you gonna do some computational intensive work, when you need the power of CPU.)

    对于 Async 扩展而言,不管是 I/O 密集型还是计算密集型的代码,都可以通过类似的方式来调用。下面是一个例子,其中可能会分配一个线程池线程来执行计算,而 UI 线程则通过 await 关键字等待直到计算完成:

    async void ComputeStuffAsync(){
        double result = 0;
        await TaskEx.Run(()=>{
            for (int i = 1; i < 500000000; i++) {
                result += Math.Sqrt(i);
            }
        });
        MessageBox.Show("the result is " + result,
            "Background Task",
            MessageBoxButton.OK, MessageBoxImage.Information);
    }

    Anders 还简要介绍了 Async 扩展的实现原理。其大致思想,是通过编译器,将 asnyc / await 关键字等组织的代码,编译为状态机 (state machine) 来控制执行流程。当多个异步操作互相调用,形成一系列异步操作组成的组合操作时,编译器就会将其编译为通过 continuation 的方式串接起来的一个一个的操作序列。这里创建状态机的思想其实和 C# 2.0 yield 关键字的实现如出一辙,但是编译器在背后所做的工作更加复杂化和智能化了。

    感觉上,C# Async 的功能实现了类似于 F# 中的异步工作流的优秀特性。在 Anders Hejlsberg 的指引下,我们有理由对 C# 的未来充满信心,其一定会不断实现和采纳其他语言所具有的各种优秀的语言特性到 C# 中,从而使 C# 编码更加爽快和便捷。

    在讲座结束前,Anders 还花一点时间介绍了 Compiler as a Service. 就是将编译器开放为一种可在代码中调用的服务。其中一个 demo 却因为 Visual Studio 的什么原因而导致演示失败了。

    对并发编程的支持:在提问环节,Anders 回答说 Concurrency 目前还是以库的方式提供支持 (.NET 4.0),而没有实现为语言特性。在语言支持的方面目前也在进行着一些努力。

    欲了解详情,可下载 Visual Studio Async CTP 进行体验。

    PS: 老赵已对 Anders 的这次演讲进行了更为详尽的解读,强烈推荐大家阅读老赵的文章,以获得全面的了解。

  • 相关阅读:
    父子进程 signal 出现 Interrupted system call 问题
    一个测试文章
    《淘宝客户端 for Android》项目实战 html webkit android css3
    Django 中的 ForeignKey ContentType GenericForeignKey 对应的数据库结构
    coreseek 出现段错误和Unigram dictionary load Error 新情况(Gentoo)
    一个 PAM dbus 例子
    漫画统计学 T分数
    解决 paramiko 安装问题 Unable to find vcvarsall.bat
    20141202
    js
  • 原文地址:https://www.cnblogs.com/RChen/p/1865581.html
Copyright © 2011-2022 走看看