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 的这次演讲进行了更为详尽的解读,强烈推荐大家阅读老赵的文章,以获得全面的了解。

  • 相关阅读:
    继续JS之DOM对象二
    js之DOM对象一
    js之DOM对象三
    jQuery基本语法
    Jquery2--属性相关的操作
    jquery之文档操作
    jQuery之jQuery扩展和事件
    Bootstrap补充
    函数式编程
    数据结构,字典
  • 原文地址:https://www.cnblogs.com/RChen/p/1865581.html
Copyright © 2011-2022 走看看