Hello World
Spiga

PDC 2010:C#与Visual Basic的未来(中)

2010-10-31 21:49 by 老赵, 5056 visits

前几天在PDC 2010会议上Anders Hejlsberg发表了一场名为“The Future of C# and Visual Basic”的演说,谈论了未来C#和VB中最为重要的两个特性:“异步(Async)”及“编译器即服务(Compiler as a Service)”。我现在对这场演讲进行总结,但不会像上次《编程语言的发展趋势及未来方向》那样逐句翻译,而是以Anders的角度使用一种简捷合适的方式表述其完整内容。上一篇Anders讲述了async和await的使用方式,而这篇则是对这两个关键字的实现及效果作更进一步的解释。

异步方法的目标,是为了让代码与同步方法保持一致。微软要让代码充斥着回调函数,混乱不堪,它们完全不是逻辑上你想做的事情。可能您的代码中包含着一个核心模型,你也已经实现了,只是您现在想把它的执行过程变得异步化。您自己就可以享受到这一点。

与我们之前做的一些扩展一样,工作分为语言和框架两部分。语言的异步功能基于框架中的Task<T>,我们会围绕着Task<T>扩展框架,将它作为异步模型的核心。事实上,从Begin/End,或是基于事件的异步模型进行扩展往往只需要一两行封装的代码,于是您也可以得到自己的Task<T>模型。

而在语言方面,我们添加了两个新的关键字。一个是async关键字,用于把方法标记为异步。还有一个是await方法,用于等待异步工作完成,或者说是把控制权交换给调用方继续执行其他工作。这两个功能在C#和VB种均有体现。

那么什么是Task<T>呢?它表现的是一个“后续会继续进行的操作”,这可以是许多东西,Task<T>并不做任何限制,例如是一个异步I/O,后台工作线程等等,甚至可以是UI上的一个按钮,在用户点击之后任务就结束了。

Task<T>的优势在于,它使用一个对象封装了整个概念,您可以查询其结果或是状态,或是这个任务所引发的异常。您可以用它来构造一个可组合的异步模型,这正式我们目前的异步编程模型所不足的地方。

此外,它还提供了一个可组合的回调模型,您可以对一个任务指定说,在它结束之后执行另外一段代码,然后还可以对这个新的任务继续进行设定。这便构造出一个完整的逻辑流,框架会自行帮你完成这些工作。事实上await操作符便会自动把您的逻辑改写成这样的代码,它将您从Lambda表达式及回调函数中的逻辑里解放了出来,一切都交给编译器去做了。您可能会有些疑惑,不过其实这些都是编译器所擅长的事情。

由于我们统一了异步模型,我们就可以在此之上构建组合工具。例如WhenAll,它接受一系列的Task对象,并在全部结束之后返回所有结果。还有WhenAny,则等待第一个完成的任务,返回其结果。我们还有Delay,可以等待一段时间,但不占用任何资源。

沿着这个过程走一遍可能就会清晰一些。这里有个例子,一个异步方法调用另一个异步方法。我们假设这是在UI线程上执行的,消息会一个一个发送至UI线程上。

好,有人调用了DoWorkAsync,于是出现了一些任务。

DoWorkAsync的第一件事,是调用了ProcessFeedAsync。

ProcessFeedAsync方法是一个异步方法,所以它做的第一件事是构造一个表示任务的Task对象。

然后它调用了DownloadFeedAsync,这会创建另一个Task对象。然后,我们遇上了await操作符,这意味着ProcessFeedAsync后面的部分,将作为DownloadFeedAsync完成后的回调函数/continuation里的工作。

于是任务返回至DoWorkAsync,我们得到了t1这个对象。

同样的过程会再次出现,是为t2。

然后便调用了Task.WhenAll,这会创建一个新任务,表示前两个任务全部完成。于是这里的await操作符表示接下去的代码会在前两个任务完成后再继续下去。此时控制权便还给了DoWorkAsync的调用者,不会对线程造成负担。

在未来某一时刻t1和t2会执行完,我们假设t2先结束。此时它会说:我完成了,执行回调函数/continuation吧。

于是它会和发起线程的SynchronizationContext交互,给UI线程发一个消息,让后续任务在UI线程上继续执行──您的代码不用关注这些。现在代码运行至SaveDocAsync上了,这是另外一个异步任务。await让代码在这里返回,线程又可以执行目前还未结束的任务了。

于是SaveDocAsync任务完成了,UI线程又获得了一个消息执行后续工作。

此时任务便到达了ProcessFeedAsync的末尾,于是t2任务结束了。

继续等待,上面的过程会再次出现,最终t1也结束了。

当t1和t2完成以后,最后DoWorkAsync任务也终于结束了。可以看到,我们逻辑流程,无论是循环还是异常捕获都是同步的,但是其中的执行过程完全是异步的。

但是这又是如何实现的?我不会在这里说太细,这又是个完整的话题了。这里有一个例子,是一个异步方法,它会调用并await另一个异步方法。

而编译器则最终则生成类似于这样的代码。我只会提几点,首先,这是个状态机,编译器构造的其实就是个状态机,例如迭代器就是个状态机,事实上这里编译器的工作和yield之余迭代器的重写本质上没有太大区别。

其次就是关于任务的执行和等待,假如在等待时任务已经完成了,那么其实您是在同步地执行后续代码。我们没有必要交还控制,反正已经完成了,我们不妨就直接进行下去了。await有自己的模式,会决定这一任务是同步还是异步地执行。对于同步执行的任务,一切就继续执行下去了,直到某个需要异步执行的地方,便把控制权交还给调用方。

那么我们再来看一下异步之于Web服务的意义。这里有个ASP.NET页面,它会向数据库里获取许多RSS地址,然后下载到本地并解析:

private void ProcessData()
{
    // ...

    var urls = new List<string>();
    using (var conn = new SqlConnection(connectionString))
    {
        conn.Open();
        var cmd = new SqlCommand("GetUserFeeds", conn);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("@UserID", user);
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read()) urls.Add(reader["FeedURL"].ToString());
        }
    }

    var feeds = (from url in urls select CreateWebClient().DownloadString(url)).ToArray();

    // ...
}

这里用到了DownloadString这个同步下载数据的方法。执行下来大约要花费1秒多的时间。这里我不再演示令人痛苦的异步写法了,你必须在Page_Load和Page_PreRender各写一些逻辑,注册一些异步工作,或者就要启用一些后台线程,但这又会影响后台的线程池,对系统的表现会带来影响。

现在我来演示一些简单的异步化工作:

private async void ProcessData()
{
    // ...

    var urls = new List<string>();
    using (var conn = new SqlConnection(connectionString))
    {
        conn.Open();
        var cmd = new SqlCommand("GetUserFeeds", conn);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("@UserID", user);
        using (var reader = await cmd.ExecuteReaderAsync())
        {
            while (reader.Read()) urls.Add(reader["FeedURL"].ToString());
        }
    }

    var feeds = await TaskEx.WhenAll(
        from url in urls select CreateWebClient().DownloadStringTaskAsync(url));

    // ...
}

我们将DownloadString修改为DownloadStringTaskAsync,这样LINQ返回的就是一系列表示下载任务的Task对象,然后使用await及WhenAll等待它们全部完成。数据库查询也可以如此。这就是所有我们要做的事情。如今页面的执行效率有了很明显的提高。使用这个做法,我们可以很轻松地提高Web系统的伸缩能力。如今我们需要调用很多互相独立的服务的情况越来越多了,异步方法对此有很大帮助。

如今的异步场景有许多种,例如在后台执行一个计算任务,这是基于CPU的异步,还有基于网络或I/O的异步任务。这些都能用Task来表示出来,因为Task表示的就是未来会完成的异步任务。此外,有了async和.NET框架,我们则出现了另外一种任务,既基于某些任务组合而成的异步任务。这也就是async方法所体现出的异步任务,它可以让你使用传统的语句来构造异步执行过程。

例如有这么一个场景:获取链接,根据链接下载Youtube视频,根据下载到的视频创建mashup并组合起来。在执行这些工作的时候,我们也希望UI可以响应用户操作。

而要完成这些工作,代码可能只需要这么简单,完全就像同步代码一样。而这里也体现了多种异步任务:ScrapeYoutubeAsync是网络密集型任务,然后同时下载两个视频并等待它们结束。然后MashupVideosAsync是CPU密集型任务,然后最后则是I/O密集型的的SaveAsync操作。对于异常处理来说,我们可以简捷地使用一个try...catch,就像传统编程那样。

总结一下,一个异步方法可以让代码和同步实现一样简单,并统一了计算、网络及I/O的异步化。这可以用来创建高度伸缩的服务器程序,自然还有响应度高的UI程序。

在演讲的末尾,我会给出Visual Studio Async CTP的下载链接,我很乐于得到大家的反馈。

相关文章

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

80 条回复

  1. niok
    183.14.248.*
    链接

    niok 2010-10-31 23:28:31

    这不跟F#的特性重合了么?纠结啊

  2. 老赵
    admin
    链接

    老赵 2010-10-31 23:37:57

    @niok

    虽然原理不同,但的确是为了相同的目的的。不过要说起来,C#和VB重合度不更高吗?怎么没有人有这方面困扰呢?没人说过出了一个F#就必须精通,就像没人说有精通C#后还得精通VB。

  3. Duron800
    117.79.83.*
    链接

    Duron800 2010-10-31 23:58:38

    下周跟进老赵的这个系列。

  4. niok
    183.14.248.*
    链接

    niok 2010-11-01 00:11:36

    @老赵

    有道理。用F#写了一两周程序了,还不顺手,主要是思维一时难以转变,老赵在这方面花了多长时间才写得顺手的呢?C#在异步这方面的语言特性是不是要在下个版本才会正式发布呢?

  5. 老赵
    admin
    链接

    老赵 2010-11-01 00:28:58

    @niok

    我大学里接触过函数式编程,所以F#用起来比较容易的。

    C#的下一版本,估计至少也要在2012年后半段出来了吧,之前也会有较多修改,就像当时作dynamic的时候,在使用模式上也是权衡了好多遍。

  6. tinytian
    222.66.163.*
    链接

    tinytian 2010-11-01 09:34:35

    怎么又见楼上这种人啊!

  7. 链接

    sinsaychen 2010-11-01 09:34:57

    本来想驳一下LS的,结果想了一想...确实还真是那么一回事儿...

  8. 九拍
    210.13.83.*
    链接

    九拍 2010-11-01 10:02:52

    lz可以考虑搞个图床,现在点击看大图,比较不给力。

  9. 老赵
    admin
    链接

    老赵 2010-11-01 10:38:08

    @九拍

    没办法,VPS,性能不高啊。图片还是自己统一管理的好。

  10. ming
    61.174.24.*
    链接

    ming 2010-11-01 10:43:10

    总算看完了,这个改进相当爽啊~ 如果用过这个再去用传统的异步,感觉肯定会相当痛苦

  11. abc
    61.135.195.*
    链接

    abc 2010-11-01 11:05:57

    这种高度抽象的封装对设计框架的人的要求很高。

    在设计调试的环节不能出现一丁点底层的东西,也就是说不能有抽象泄露。

    举个例子,如果某句代码有一个底层错误需要处理,可能就很麻烦了。这个机制如果结合STM就更完美了。

    这个我要再写点东西,先mark。

  12. 链接

    小城故事 2010-11-01 11:08:44

    请教一下老赵,你文章里的代码块是怎么嵌入的,和VS里看到的一样呢

  13. 老赵
    admin
    链接

    老赵 2010-11-01 11:16:57

    @小城故事

    Windows Live Writer有个插件叫做Paste from Visual Studio,这也是我时不时用个Windows虚拟机最主要的原因了。

  14. doylecnn
    222.68.249.*
    链接

    doylecnn 2010-11-01 16:23:20

    @mcpssx

    自己懒,长了腿不愿意直立起来解放双手

    还要到处叫,说只用两只脚走路,速度慢,解放出来的两只手多余,直立起来保持平衡浪费运算

    毕竟四足走路到二足走路解决的不是实质问题

    毕竟实质的问题要等到由于有足够多的需求需要二足走路后,生理方面进化到合适二足走路

    不过,没关系,四足走路的会继续进化到,比如出现地面最快的豹子

  15. 链接

    陈梓瀚(vczh) 2010-11-01 17:39:00

    因为有了容易的工具就放弃深入学习原理的人,怪谁啊,微软又不是大学,干嘛非得保证你们人人都精通原理,能保证你们都完成得了公司给的任务已经很不错了。

  16. mathgl
    222.216.162.*
    链接

    mathgl 2010-11-01 19:37:35

    我现在构建的 real-time gps vehicle tracking system的server就是基于 iocp和 .net 4.0 的tpl。一台普通的电脑可以管理上万的长连接,响应度也不错。

    同样的程序略加改动可以使用mono在linux下跑。当然这不是什么热门的东西,不能和tomcat之类的比较了。

  17. icoxsm
    113.110.181.*
    链接

    icoxsm 2010-11-01 21:53:11

    客观的说,微软有很多技术是很好,但.net是靠钱和广告砸出来的,这个东西做客户端又大又慢,做服务端?不知道有什么知名网络框架是用.NET技术做的。

    VS2010我装了一天,就卸了,公司电脑2G内存,集成显卡,一卡一卡的。 家里4G内存,独立显卡,没公司那么卡,也没VS2008快,还是卸了。 什么时候用C++把 VS的界面重写一遍啊,像vc6一样。

    .NET做的客户端就是个杯剧。

  18. 老赵
    admin
    链接

    老赵 2010-11-01 22:14:15

    @icoxsm

    .NET通用框架是不多,因为社区在这方面做的不够好。Code Snippet很多,大家都是做到表现个能力出来,就感觉OK了。不过.NET的应用相当多,性能也好,就够了。

    我公司的机器一直是2G内存,显卡没关心过,用VS2010很顺畅,一开还是3、4个项目,我已经忘了VS2008是什么感觉了。

  19. 老赵
    admin
    链接

    老赵 2010-11-01 22:20:32

    忽然想到:微软用微软技术做的好,别人用微软技术做不好,问题出在微软技术上。别人用逼人技术做得好,微软用别人技术做不好,问题还是出在微软公司身上。

    可怜的微软,我对于这种双重标准真心感到很无语。

  20. Eric
    27.36.158.*
    链接

    Eric 2010-11-01 22:20:58

    这年头真的什么人也有。讨论可以,有必要咬着不放?就算老赵真的被你洗脑了,反转枪头跟你一起天天骂.NET,又能怎样,用.NET依然继续用,不用.NET的依然不用,靠.NET数钱的开发公司继续数钱,靠在网上装下逼满足自己的高手梦的依然只能装下逼满足自己的高手梦。

  21. Eric
    27.36.158.*
    链接

    Eric 2010-11-01 22:25:35

    顺便说一下,国内主流的开发语言/平台:Java、PHP、.NET、C++通通都有人用得不爽,通通都被人骂过,但就是这些大家来找碴的技术养活了一大批公司和一大批人。

  22. 老赵
    admin
    链接

    老赵 2010-11-01 22:26:10

    @Eric

    只要说的靠谱,我倒觉得咬着不放没有任何关系。还有就是,不同意我说的也罢,但我最怕听不懂我在说什么,不断重复,重复……

  23. harry
    58.34.124.*
    链接

    harry 2010-11-01 23:49:14

    @icoxsm

    羡慕你还能成功卸载,以前装个vs2008,用了不久不知怎么坏了,后来卸载后,重装不了,折腾半天结果只能重装系统,嘿,能装了。

    前段时间在xp上装了个vs2010尝鲜,由于长期不用,今天想卸载,结果连着报错,一气之下找到相关文件直接删除,俺实在玩不会这玩意。。。。。。。

  24. Duron800
    117.79.232.*
    链接

    Duron800 2010-11-02 00:13:41

    老赵还是不要回复那个人的无聊的问题了。弄得回复这么长,可有用的又不多。

    与我们之前做的一些扩展一样,工作分为语言和框架两部分。语言方面的异步工作是基于Task的

    下一段开头也是语言方面,上面这个引用里的应该是框架方面吧?

  25. 老赵
    admin
    链接

    老赵 2010-11-02 00:19:39

    @Duron800

    没写错,不过我改了一点,就不会有误解了,呵呵。

  26. 链接

    Ivony 2010-11-02 02:14:15

    虽然斗嘴很好看,但基本上永远都是各说各的。。。。

    mcpssx说的有些不无道理,但是老是抓着.NET性能不佳被放弃的辫子显然是不够的。

    一个公司放弃某种技术使用某种技术一定都有复杂的从上到下的问题存在,当然在放弃一种技术的时候总要数落一番这种技术的缺点。.NET最为人所知的就是性能欠佳(我没说这是事实,只是买菜老太他家儿子都听说而已),所以这种声明其实毫无意义。

    就像导演不选择某个女演员一样永远宣称是演技问题一样,说不定是长相和宾馆里的问题。

    为什么没有用.NET写的XXX这样的论调则更说明不了任何问题,难道说没有钻石做的菜刀就说明钻石切不了菜?

    每一个东西都有自己的定位,不能说,.NET的改进与你的期望不相符,就是垃圾和毫无意义的。或者说,不去改善你所需要的东西就是不务正业。

    微软也没有必要为了初学者更能了解原理而将语言简化成一种任何事情都要清晰的描述原理和步骤的样子,如果要了解执行原理的话,写汇编岂不更好?C#和C++本来就是定位不同的语言。或者说C#本来就不是一种教学用语言,

  27. 链接

    Ivony 2010-11-02 02:27:46

    两个建议啊:

    1、因为代码基本上要放大图才能看到,所以为啥不将代码作为文本形式放在最后呢。

    2、这段文字:

    在未来某一时刻t1和t2会执行完,我们假设t2先结束。此时它会说:我完成了,执行回调函数/continuation吧。

    这里的描述很容易让人迷糊(我承认我迷糊了一下),准确的说是t2里面的await DownloadFeedAsync(url);执行完成了,而不是t2结束或者完成。

    建议修改为:

    在未来某一时刻t1和t2都会执行完成,我们先来看t2的情况,我们假设t2的DownloadFeedAsync(url)任务已经完成了。此时它会说:我完成了,执行回调函数/continuation吧。

    于是它会和发起线程的SynchronizationContext交互,给UI线程发一个消息,让后续任务在UI线程上继续执行──您的代码不用关注这些。现在代码运行至SaveDocAsync上了,这是另外一个异步任务。await让代码在这里释放UI线程,UI线程又可以执行目前还未结束的任务了。

    于是SaveDocAsync任务完成了,UI线程又获得了一个消息执行后续工作。

    此时任务便到达了ProcessFeedAsync的末尾,于是t2任务结束了。

  28. 链接

    Ivony 2010-11-02 02:34:00

    这个幻灯片应该是Anders弄的吧,我在想,这一段可能他原本打算是让t1和t2在UI线程上交错执行的,因为这样才能更好的说明异步使得线程的利用率大大提高。但是如果流程画成那样的话,就更难讲清楚了。

    不过,我看了半天,觉得

    于是它会和发起线程的SynchronizationContext交互,给UI线程发一个消息,让后续任务在UI线程上继续执行

    这里好像是很闪的亮点啊。

  29. Ricepig
    221.223.87.*
    链接

    Ricepig 2010-11-02 08:12:53

    额,我怎么发现await和async这个原理讲解,就很像WinAPI里的WaitAny这些非繁忙等待哇。。。

    当初从《Win32多线程编程》这本书就看到了这个非忙等待的方法,终于直接被某种语言直接支持了,确实省了不少事情

    不过,语言封装的东西太多,对于入门者来说,不了解来龙去脉就直接使用,容易有误区吧,呵呵。尤其是以前没有经历过while(WaitAny(...)){}这种代码,还真不知道咋回事了。

  30. Ricepig
    221.223.87.*
    链接

    Ricepig 2010-11-02 08:18:19

    楼上某位老要把C++和C#比,说C#没有libevent的轮子党童鞋

    我是不是可以说,因为在某些操作系统中还在用汇编情况下,C++和汇编比就是烂货呢?

    抨击C#的性能是没有问题的,但是老赵说的只是async会让C#的伸缩性“更”好,这有啥问题呢。难道C++性能比汇编差,就说明C++性能很差吗?

    那大家都去写机器码好了哇,不但速度快,而且不用编译了呢。

    语言其实有的时候也是一个平衡的艺术,有得有失,每一门语言都有它的适用范围。

    对于C++语言,大家就很爱做轮子党,什么都自己做一个,都觉得挺好挺牛逼。

    对于C#语言,类库完整的多,轮子党相对来说就没那么多,而且C#的优势其实也是在快速开发。拿C#和C++比那一点性能优势,就和用C++和汇编比那一点性能优势差不多吧。

  31. waynebaby
    64.71.140.*
    链接

    waynebaby 2010-11-02 09:01:21

    并没有rx那么激动人心嘻嘻

  32. waynebaby
    112.64.190.*
    链接

    waynebaby 2010-11-02 09:16:14

    为什么代码复用不高?因味那时候没有好的mvvm框架,现在有

    实施人做得烂,大多是领域不熟悉,项目沟通不好

    如果这和技术有关就有趣了,因为类似问题c++遇到的更多

    大家都知道的字体问题不是早解决了么?我现在也不能指责恁没断奶。

    不可用的技术一定要上,这是纽约时报管理腐败。

  33. waynebaby
    112.64.190.*
    链接

    waynebaby 2010-11-02 09:20:07

    一个放视频的网站,性能的好坏主看链接速度和解码速度。别的图形加速测试你可以满大街搜,flash真没什么优势,

  34. 链接

    zsbfree 2010-11-02 10:44:18

    不明白老赵为什么和他辩论。。。 有些人就是那样。。。因为和一个xx辩论的结果是把自己也变成了一个xx.. 期待你更好的文章。 老赵把博客转移到这里是明智的,博客园现在差不多快成了垃圾新闻的场地了 也不知道创始人是怎么想的。。

  35. 链接

    zsbfree 2010-11-02 10:46:32

    @mcpssx: 问题就是.net竞争的就是菜刀,有这么几把菜刀给你写可伸缩性的服务器架构,C的libevent, java的mina等等,那C#就告诉你,我们有个await的关键字可以更伸缩。那么你会怎么选择?我看这样竞争,.net必败无疑。

    败不败的管你屁事。白天没鸡巴事,晚上鸡巴没事

  36. abc
    122.70.40.*
    链接

    abc 2010-11-02 12:52:25

    等下集,看anders能把compiler as a service玩出哪些花样,有一个遗憾是那么多的这个特性那个特性,没有统一到一个简单强大的理论里面,所带来的问题是,新特性与现有语言特性的组合应用问题,这方面的工作量可能真的不小。F#在这方面的负担应该轻得多。

  37. mathgl
    222.216.162.*
    链接

    mathgl 2010-11-02 13:02:35

    所以我的观点一直是统一的:我说mono跨平台,是说它在服务器端,基本不用做什么修改,我什么时候说过它跨WPF程序了?不要把我没有说过的话拿出来说。这次我写了文章还算有个记录,否则你随口一说,好像我还真的莫名奇妙了。

    mono 目前不支持wpf。。将来我个人认为也不会有人去做这个事,如果不是不可能。跨平台的gui本来就是件很tricky又花精力的事情。现在mono对于winform的支持才是勉强可用,估计没什么精力去做wpf。看它的roadmap似乎没有这个计划。

  38. 老赵
    admin
    链接

    老赵 2010-11-02 13:12:25

    @mathgl

    mono不做跨平台的UI,做的是各平台原生UI的绑定。

  39. 链接

    Ivony 2010-11-02 13:14:34

    可是你忘了一件事情,纽约时报是改用AIR了,在adobe的产品中,air相当于wpf,flash相当于silverlight,就是说AIR和flash的延续性很好。

    显然这个说法是错的。。。。

    当然,关于WPF是超集的说法也是有待商榷的。毕竟WPF只是基于.NET的一套UI框架,而Silverlight不仅仅是呈现框架,还包括了一个完整的轻巧的跨平台的类似CLR的运行时。

    所以很明显,Silverlight类比于Flash是靠谱的,但AIR与Windows Presentation Framework完全是风马牛不相及的东西(MPF可能可以与其类比,如果有的话)。与AIR类比的东西,还得是Silverlight,事实上在那群头脑做出决定的时候,Silverlight已经落地(OOB)。使用WPF和Silverlight两套技术分别在Windows和OSX上开发更像是一个猪头技术总监干的事情。WPF并不是Silverlight for Windows,你可以说MS的宣传策略有问题但这显然与技术无关。

    另,对Flash早期版本有所了解的童鞋都会知道,Flash的字体问题比WPF/Silverlight恶心N倍,被恶心的时间也跨越了N年。以今天对微软苛刻的眼光来看,Flash简直比代谢产物还不如。

  40. 老赵
    admin
    链接

    老赵 2010-11-02 13:26:08

    @Ivony: 关于WPF是超集的说法也是有待商榷的。毕竟WPF只是基于.NET的一套UI框架,而Silverlight不仅仅是呈现框架,还包括了一个完整的轻巧的跨平台的类似CLR的运行时。

    我倒不是很在乎两者的Runtime的区别,主要是谈类库方面的问题。就像我也把mono、MonoTouch和MonoDroid看作是.NET,但是它们无论从运行原理都和.NET不同。他们相同的是大部分的类库、开发方式、技巧(例如表达式树构建、反射)等东西。

  41. waynebaby
    112.64.190.*
    链接

    waynebaby 2010-11-02 13:56:26

    air 就是多个flash 打个zip包在客户端假装本地程序运行。 和安装在桌面的silverlight4一个路数。

  42. waynebaby
    112.64.190.*
    链接

    waynebaby 2010-11-02 13:57:02

    所以说,某人说的air相当于wpf 是根本不懂air啊。。哈哈

  43. 老赵
    admin
    链接

    老赵 2010-11-02 13:59:01

    @waynebaby

    原来AIR相当于Silverlight桌面版啊,唉,我也土了。

  44. RMay
    218.80.238.*
    链接

    RMay 2010-11-02 14:44:59

    @mcpssx

    1、从C++写的换到WPF,性能下降,这很正常,在XP上就是。因为XP操作系统的渲染方式就不是DirectX的,Vista和Win7上的表现则完全不一样。我想,3.0的时候,还是以XP的机子为主吧?

    2、WPF字体渲染的问题,在4.0里面已经搞定了。就算是3.0/3.5,你也可以自己写个TextBlock,用GDI来渲染字体,照样很清楚。其实,我最想问的是,你做过WPF/SL的开发么?知道这两个东西是咋回事么?只靠道听途说,不太好吧?

    3、如果你那么在意跨平台(客户端),那么确实,请别用.Net了。但实际上,你用java什么的,就能保证你的代码完全没有问题了么?IBM和SUN的虚拟机还不一样呢,照样出很多诡异的问题。

    4、文中提到的异步编程方式的改进,说实在的,在我看来,跟是不是.Net,是不是C#,屁关系都没有,如果你搞个X#语言也能如此提高生产效率,那我就用这个去。

  45. 老赵
    admin
    链接

    老赵 2010-11-02 18:04:15

    @mcpssx

    之前都说了,Flash和AIR相当于Silverlight和Silverlight离线版。你非要拖一个WPF上来混战,说它和Silverlight不兼容是个错误,太能找茬了。你怎么不说WPF可以做到AIR所做不到的事情呢?

  46. driedbeef
    113.76.81.*
    链接

    driedbeef 2010-11-02 22:52:15

    Anders这个Session的视频我也在PDC网站上看了,感觉还不赖。

    将一些共性的东西,优美的解决方案逐渐沉淀到框架和语言当中,可以说是一种必然趋势,这在.NET Framework/C# Language当中做得似乎“过于成功”了。个人很喜欢这种“语法糖”,不过我更愿意去探究编译器在这些“魔法”背后做了什么,设计者经过了哪些抽象和纠结,得到的解决方案。

    让程序和机器去做这些模式化的体力活,将写程序的人解放出来做更高层次的思考。做不到前者的人没有现在,做不到后者的人没有未来。

  47. 链接

    陈梓瀚(vczh) 2010-11-03 17:25:25

    @driedbeef

    那你可以跟我一样没事在vlpp.codeplex.com上写个编译器做点研究什么的,就可以同时享受知识和.net带来的双重乐趣了哈。

  48. driedbeef
    113.106.106.*
    链接

    driedbeef 2010-11-03 18:23:00

    @陈梓瀚(vczh)

    高科技产品,有空研究一下。

  49. bluetrees
    222.70.192.*
    链接

    bluetrees 2010-12-21 12:49:59

    async和await这两个语法糖,的确是革命性的改进,他把并行计算的模型从Thread使用中解放出来。

    但也不是完全没有毛病的,默认的task的调度器在很多场合不适用,此外,任务队列也太重。我往文件里面并行的插入10万条记录,我用async和await组合,先产生了10万个任务,用了0.7秒,这些任务全部完成用了20秒。我用传统的创建Thread的方式并行插入,10个线程,每个线程插1万条,0.6秒就完成了,也就是说产生10万个任务的时间甚至超过了插入实际的记录的时间。为了对比,我用一个线程插入10万条记录,用了1.07秒。

    这挺能说明说明那个调度器的效率的。

  50. 老赵
    admin
    链接

    老赵 2010-12-21 16:22:12

    @bluetrees

    往文件里并行插入有没有代码可以看看?其实async和await其实只是辅助异步工作,并行计算的基本原则还是要遵守的。

    例如你创建了10万个任务,这就是用法上的问题了,应该把大任务切分成少量的任务,每个任务多做点事情。其实你原本用10个线程工作,现在用10个任务就行了。我在使用的时候没有遇到过调度上的性能问题,调度器效率再高,调度10万个任务开销也是很夸张的,不能这么比。

  51. 链接

    airwolf2026 2012-05-18 13:55:40

    how does it work 那节编译器生成的代码,有点2.x时代的begin/end的感觉哈哈.那个真是头痛的使用方式,我第一次接触.net异步编程的时候,以为框架提供的 就是类似async和await的相识用法的,结果看了msdn看了半天一头雾水,原来没有那么自然的表达. 期待win8普及哈.现在产品还是2.0写的.

  52. 老赵
    admin
    链接

    老赵 2012-05-20 12:41:08

    @airwolf2026

    本来就是编译器帮你生成丑陋的代码嘛。

  53. larz
    114.44.169.*
    链接

    larz 2012-11-14 06:56:27

    看了不少async/await的介绍,大致了解相关机制后,产生了一个疑问。

    只用async的话,那还是同步方法,要搭配await才算异步方法,看起来async只起了一个标记的作用。

    编译器可从上下文是否使用await来推断同步或异步,进行相应的改写,那么async就显得有些多余。

    我还没看过有人质疑这点,是否async关键字除了标记作用,还有其他其必不可少的作用?

  54. 老赵
    admin
    链接

    老赵 2012-11-14 10:37:59

    @larz

    强制标记,用来让程序员看清楚,而不是编译器看清楚。

已自动隐藏某些不合适的评论内容(主题无关,争吵谩骂,装疯卖傻等等),如需阅读,请准备好眼药水并点此登陆后查看(如登陆后仍无法浏览请留言告知)。

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我