对[yield]的浅究到发现[async][await]
原文:对[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]的更多相关文章
- 对[foreach]的浅究到发现[yield]
原文:对[foreach]的浅究到发现[yield] 闲来无事,翻了翻以前的代码,做点总结,菜鸟从这里起航,呵呵. 一.List的foreach遍历 先上代码段[1]: class Program { ...
- 理解ES7中的async/await
理解ES7中的async/await 优势是:就是解决多层异步回调的嵌套 从字面上理解 async/await, async是 "异步"的含义,await可以认为是 async w ...
- async await 的 实质 本质
async await 的 实质 就是 用 “状态机” 来 取代 函数层层调用 . async await 的 本质 是 语法糖, 和 提高性能 什么的 没什么关系 . 为了避免理解歧义, 我把 ...
- 我 支持 使用 async await
这篇文章原来的 标题 是 <我 反对 使用 async await>, 但经过后来的一些研究, 发现 async await 是 良性 的, 所以 我把 标题 改成了 <我 支持 使 ...
- [转] 理解 JavaScript 的 async/await
[From] https://segmentfault.com/a/1190000007535316 边城 2016年11月19日发布 随着 Node 7 的发布,越来越多的人开始研究据说是 ...
- 深入理解理解 JavaScript 的 async/await
原文地址:https://segmentfault.com/a/1190000007535316,首先感谢原文作者对该知识的总结与分享.本文是在自己理解的基础上略作修改所写,主要为了加深对该知识点的理 ...
- 七 vue学习 async/await
1: javaScript async/await: 调用async函数的时候,是异步的,函数后面的代码继续执行.! async / await是ES7的重要特性之一,也是目前社区里公认的优秀异步解 ...
- 理解 JavaScript 的 async/await
随着 Node 7 的发布,越来越多的人开始研究据说是异步编程终级解决方案的 async/await.我第一次看到这组关键字并不是在 JavaScript 语言里,而是在 c# 5.0 的语法中.C# ...
- 深入理解协程(三):async/await实现异步协程
原创不易,转载请联系作者 深入理解协程分为三部分进行讲解: 协程的引入 yield from实现异步协程 async/await实现异步协程 本篇为深入理解协程系列文章的最后一篇. 从本篇你将了解到: ...
随机推荐
- zoj 2156 - Charlie's Change
称号:拼布钱,表面值至1,5.10.25.寻求组成n表面值硬币的最大数目. 分析:dp,01背包.需要二元分割,除此以外TLE.使用每个硬币的数组记录数.轻松升级. 写了一个 多重背包的 O(NV)反 ...
- Spring.Net控制翻转、依赖注入、面向切面编程
Spring.Net快速入门:控制翻转.依赖注入.面向切面编程 Spring.Net主要功能: 1.IoC:控制翻转(Inversion of Control) 理解成抽象工厂翻转控制:就是创建对象 ...
- android--jenkins+gradle+android自动化构建apk步骤(转)
第一步,安装jenkins,这个网上教程挺多的. 第二步,下载并配置gradle.下载地址http://www.gradle.org/ 解压gradle至某路径下,如/usr/local/lib/gr ...
- IDF - CTF - 牛刀小试
找学校CTF好地方,IDF实验室CTF训练营(http://ctf.idf.cn/). . 刚接触CTF.来玩下牛刀小试.AK了. . 好爽好爽.. 1.摩斯password 嘀嗒嘀嗒嘀嗒嘀嗒 时针它 ...
- 运行safari提示:无法启动此程序,因为计算机中丢失 QTCF.dll
解决办法: 1.去百度搜索“QTCF.dll”,找到一个靠谱的下载地址获取到该dll文件: 2.将文件放到 安装目录:Safari\Apple Application Support 下边.
- 【Stackoverflow好问题】祛烦“!=null"()判处空语句
问题 为了避免空指针调用,我们常常会看到这种语句 ...if (someobject != null) { someobject.doCalc();}... 终于.项目中会存在大量判空代码.多么丑陋繁 ...
- 深入理解Android中ViewGroup
文章目录 [隐藏] 一.ViewGroup是什么? 二.ViewGroup这个容器 2.1 添加View的算法 2.1.1 我们先来分析addViewInner方法: 2.1.2 addInArr ...
- POJ 3126 Prime Path(BFS 数字处理)
意甲冠军 给你两个4位质数a, b 每次你可以改变a个位数,但仍然需要素数的变化 乞讨a有多少次的能力,至少修改成b 基础的bfs 注意数的处理即可了 出队一个数 然后入队全部能够由这个素 ...
- .Net程序猿乐Android发展---(10)框架布局FrameLayout
帧布局FrameLayout中全部的控件都在界面的左上側,后绘制的空间会覆盖之前的控件.布局内控件以层叠方式显示,用在游戏开发方面可能多些. 1.层叠展示 以下这个样例 ...
- ASP.NET 异步编程
ASP.NET 异步编程 相关博文: 异步编程 In .NET(回味无穷!!!) ASP.NET sync over async(异步中同步,什么鬼?) 本来这篇博文想探讨下异步中的异常操作,但自己在 ...