对[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实现异步协程 本篇为深入理解协程系列文章的最后一篇. 从本篇你将了解到: ...
随机推荐
- linux学习(一个) 在unbuntu通过添加新的用户
最近安装了双系统,开始折腾unbuntu该.Linux系统是一个多用户操作系统,非常多的人才完整的操作需要管理员权限,完全管理员权限是非常重要的.人谁是刚开始学习,般用户的权限即可了,相对于刚開始学习 ...
- 【嵌入式开发】写入开发板Linux系统-模型S3C6410
笔者 : 万境绝尘 转载请著名出处 最终拿到板子了, 嵌入式开发正式开启. 板子型号 : 三星 S3C6410 基于ARM11, 指令集基于arm6指令集; 为毛不是 Cortext A9的板子; 烧 ...
- 《TCP/IP作品详细解释2:达到》注意事项--IP地址
1.接口和地址 如下面的图全部本文中讨论的接口和地址的结构看一个示例配置: 上图中显示了我们三个接口样例:以太网接口,SLIP接口和环回接口. 它们都有一个链路层地址作为地址列表中的第一个结点. 显示 ...
- Nancy
Nancy Nancy 是一个轻量级的,简单粗暴的framework用来构建基于HTTP的各种服务,兼容.Net和Mono.Nancy的整套设计理念是基于"super-duper-happy ...
- 前端project师的修真秘籍(css、javascript和其他)
以我的经验,大部分技术,熟读下列四类书籍就可以. 入门,用浅显的语言和方式讲述正确的道理和方法,如head first系列 全面,巨细无遗地探讨每一个细节,遇到疑难问题时往往能够在这里得到理论解答,如 ...
- window批处理-4.call
作用: 批处理中调用还有一个批处理或调用行号后的全部命令 格式: call [FileName] [:label] demo: call.bat: @echo off echo 開始调用called ...
- hosts目录位置
C:\WINDOWS\system32\drivers\etc 版权声明:本文博客原创文章,博客,未经同意,不得转载.
- Task的异步模式
Task的异步模式 返回该系列目录<基于Task的异步模式--全面介绍> 生成方法 编译器生成 在.NET Framework 4.5中,C#编译器实现了TAP.任何标有async关键字的 ...
- UVa 699 落叶
意甲冠军:我几乎不记得的题意!.! 它是一个长坑..我们从根节点开始,留下每一步,保存横坐标1,正确的一步加上横坐标1. 那么同样的横坐标统计data值总和. 思维:我来想,这可以递归成就.上就能够算 ...
- ER模型
一.什么是ER模型 实体-联系图(Entity-RelationDiagram)用来建立数据模型,在数据库系统概论中属于概念设计阶段,形成一个独立于机器.独立于DBMS的ER图模型.通常将它简称为ER ...