原文:对[yield]的浅究到发现[async][await]

  上篇对[foreach]的浅究到发现[yield]写完后,觉得对[yield]还没有理解清楚,想起曾经看过一位大牛的帖子讲的很深刻(链接在此),回顾了下,在这里写出自己的理解,与各位分享。

一、通常的异步

  现在我们假设一种平时经常遇到的情况,现有三个方法,其中funcOne和funcTwo比较耗时需要异步执行,而且他们的逻辑是必须在funcOne执行完后才可以执行funcTwo,同理funcTwo执行完后才能执行funcThree。

  按照这样的设定,通常的做法请看代码段[1]:

      public class Program
{
public delegate void CallBack(string nextName);
public void funcOne(CallBack callback)
{
Console.WriteLine("[One] async Continue!");
Console.WriteLine("[One] do something!");
callback("Called Two");
}
public void funcTwo(CallBack callback)
{
Console.WriteLine("[Two] async Continue!");
Console.WriteLine("[Two] do something!");
callback("Called Three");
}
public void funcThree(CallBack callback)
{
Console.WriteLine("[Three] do something!");
callback("Called ...");
}
static void Main()
{
Program p = new Program();
//异步执行funcOne
ThreadPool.QueueUserWorkItem((state1)=>{
p.funcOne((name1) =>
{
Console.WriteLine(name1);
//异步执行funcTwo
ThreadPool.QueueUserWorkItem((state2) =>
{
p.funcTwo((name2) =>
{
Console.WriteLine(name2);
//执行funcThree
p.funcThree((name3) =>
{
Console.WriteLine(name3);
//当然还有可能继续嵌套
Console.WriteLine("End!");
});
});
});
});
});
Console.Read();
}
}

异步的通常实现

  相信看完代码后我们的感觉是一样的,好繁琐,就是不断的嵌套!那有没有方法可以避免这样呢,也就是说用同步的写法来写异步程序。

二、改进后的异步

  该[yield]粉墨登场了,先看代码段[2]:

     //三个方法以及委托CallBack的定义不变,此处不再列出。
//新增了静态的全局变量enumerator,和静态方法funcList.
public static System.Collections.IEnumerator enumerator = funcList();
public static System.Collections.IEnumerator funcList()
{
Program p = new Program();
//异步执行funcOne
ThreadPool.QueueUserWorkItem((state1) =>
{
p.funcOne((name1) =>
{
enumerator.MoveNext();
});
});
yield return ;
Console.WriteLine("Called Two");
//异步执行funcTwo
ThreadPool.QueueUserWorkItem((state2) =>
{
p.funcTwo((name2) =>
{
enumerator.MoveNext();
});
});
yield return ;
Console.WriteLine("Called Three");
//执行funcThree
p.funcThree((name3) =>
{
//当然还有可能继续嵌套
});
Console.WriteLine("Called ...");
Console.WriteLine("End!");
yield return ;
} //变化后的Main函数
static void Main()
{
enumerator.MoveNext();
Console.Read();
}

改进后的异步写法

  现在看看,是不是清爽了一些,没有无止尽的嵌套。代码中我们只需要定义一个迭代器,在迭代器中调用需要同步执行的方法,用[yield]来分隔,各方法通过在callback里调用迭代器的MoveNext()方法来保持同步。

  通过这样的实践,我们可以理解为每当[yield return ..],程序会把迭代器的[上下文环境]暂时保存下来,等到MoveNext()时,再调出来继续执行到下一个[yield return ..]。

三、是我想太多

  以上纯属瞎扯,在.net 4.5之后,我们有了神器:async/await,下面看看多么简洁吧。

  代码段[3]:

      public class Program
{
public async Task funcOne()
{
Console.WriteLine("[One] async Continue!");
Console.WriteLine("[One] do something!");
//await ...
}
public async Task funcTwo()
{
Console.WriteLine("[Two] async Continue!");
Console.WriteLine("[Two] do something!");
//await ...
}
public void funcThree()
{
Console.WriteLine("[Three] do something!");
}
public static async Task funcList()
{
Program p = new Program();
await p.funcOne();
await p.funcTwo();
p.funcThree();
//无尽的嵌套可以继续await下去。
Console.WriteLine("End!");
}
static void Main()
{
funcList();
Console.Read();
}
}

async/await

  我已经感觉到了您的惊叹之情。

  async修饰符将方法指定为异步方法(注意!:异步不异步,并不是async说了算,如果这个方法中没有await语句,就算用了async修饰符,它依然是同步执行,因为它就没有异步基因)。

  被指定为异步方法后,方法的返回值只能为Task、Task<TResult>或者void,返回的Task对象用来表示这个异步方法,你可以对这个Task对象进行控制来操作这个异步方法,详细的可以参考msdn中给出的Task解释与示例代码

  await用于挂起主线程(这里的主线程是相对的),等待这个异步方法执行完成并返回,接着才继续执行主线程的方法。用了await,主线程才能得到异步方法返回的Task对象,以便于在主线程中对它进行操作。如果一个异步方法调用时没有用await,那么它就会去异步执行,主线程不会等待,就像我们代码段[3]中Main方法里对funcList方法的调用那样。

  最后就分析到这儿吧,希望各位兄弟博友能一起讨论,共同进步。

  当然,别吝啬您的[赞]哦 :)

  

对[yield]的浅究到发现[async][await]的更多相关文章

  1. 对[foreach]的浅究到发现[yield]

    原文:对[foreach]的浅究到发现[yield] 闲来无事,翻了翻以前的代码,做点总结,菜鸟从这里起航,呵呵. 一.List的foreach遍历 先上代码段[1]: class Program { ...

  2. 理解ES7中的async/await

    理解ES7中的async/await 优势是:就是解决多层异步回调的嵌套 从字面上理解 async/await, async是 "异步"的含义,await可以认为是 async w ...

  3. async await 的 实质 本质

    async await  的 实质 就是 用 “状态机” 来 取代 函数层层调用 . async await  的 本质 是 语法糖,  和 提高性能 什么的 没什么关系 . 为了避免理解歧义, 我把 ...

  4. 我 支持 使用 async await

    这篇文章原来的 标题 是 <我 反对 使用 async await>, 但经过后来的一些研究, 发现 async await 是 良性 的, 所以 我把 标题 改成了 <我 支持 使 ...

  5. [转] 理解 JavaScript 的 async/await

    [From] https://segmentfault.com/a/1190000007535316      边城 2016年11月19日发布 随着 Node 7 的发布,越来越多的人开始研究据说是 ...

  6. 深入理解理解 JavaScript 的 async/await

    原文地址:https://segmentfault.com/a/1190000007535316,首先感谢原文作者对该知识的总结与分享.本文是在自己理解的基础上略作修改所写,主要为了加深对该知识点的理 ...

  7. 七 vue学习 async/await

    1:  javaScript async/await: 调用async函数的时候,是异步的,函数后面的代码继续执行.! async / await是ES7的重要特性之一,也是目前社区里公认的优秀异步解 ...

  8. 理解 JavaScript 的 async/await

    随着 Node 7 的发布,越来越多的人开始研究据说是异步编程终级解决方案的 async/await.我第一次看到这组关键字并不是在 JavaScript 语言里,而是在 c# 5.0 的语法中.C# ...

  9. 深入理解协程(三):async/await实现异步协程

    原创不易,转载请联系作者 深入理解协程分为三部分进行讲解: 协程的引入 yield from实现异步协程 async/await实现异步协程 本篇为深入理解协程系列文章的最后一篇. 从本篇你将了解到: ...

随机推荐

  1. XXTEA 加密算法 C++ C#兼容版本号

    1.一个不错的可逆加密算法XXTEA 之前无意中看到了TexturePacker 使用了XXTEA来加密图片资源.所以花了点时间来看了下XXTEA. 一般有两种加密算法:1.像md5,SHA1,等ha ...

  2. RunJS推荐用于个人使用(使用方便JS、css实时预览、编辑、管理等功能)

    RunJS,在线编写.展示html.js.css代码,拥有实时预览.分享.Fork.代码高亮.自己主动完毕等多项特性,提供文件上传.多种登录方式. 地址:http://runjs.cn/ waterm ...

  3. 认识input输入框的placeholder属性

    我们来认识下input输入框的placeholder属性. placeholder 属性提供可描述输入字段预期值的提示信息.(placeholder 属性适用于以下的 <input> 类型 ...

  4. Following unknown configure options were used:--enable-fpm

    跑cd   php-5.2.13安装时间 ./configure --prefix=/usr/local/php/ --with-config-file-path=/usr/local/php/etc ...

  5. 使用shell/python获取hostname/fqdn释疑(转)

    一直以来被Linux的hostname和fqdn(Fully Qualified Domain Name)困惑了好久,今天专门抽时间把它们的使用细节弄清了. 一.设置hostname/fqdn 在Li ...

  6. 关闭 MsMpEng.exe

    MsMpEng.exe是Windows Defender 自动保护服务的核心引擎. 系统是win8.1 最近发现MsMpEng.exe是任务管理器里面最占内存的一个程序,且无法强制结束程序.偶然发现一 ...

  7. 实现android里面WebView显示内容

    在日常学习.我们会看到,当手机应该检查注册协议.单击协议时,以查看内部协议的全部内容! 以下给大家看看实现的过程: 首先贴show_xy.XML代码: <WebView android:layo ...

  8. UVa 10190 - Divide, But Not Quite Conquer!

    称号:给你第一个任期的等比数列和倒数公比,最后一个条目假定1这一系列的输出,否则输出Boring!. 分析:数学.递减的.所以公比的倒数一定要大于1.即m > 1. 然后在附加一个条件n  &g ...

  9. ORDER BY RAND()

    大概是因为需要研究了一下MYSQL随机样本实现.例如:离tablename表随机抽取了创纪录,我们一般的写法是:SELECT * FROM tablename ORDER BY RAND() LIMI ...

  10. 7 Ways to earn money on programming(转)

    英文原文:7 Ways to earn money on programming 几个星期前,当我收到一个自称 Someone712 的人发给我的一条消息时,我决定要写一篇如何用编程赚钱的博客文章.S ...