今天要记录的内容摘要是:

什么时候异步代码能“等”在那里,什么时候不会“等”

这两天Coding的时候碰到一个事儿,就是想让异步等在那里结果却直接执行过去了,比如这样:

         async static void Count()
{
Console.WriteLine("Task Void 开始");
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
int count = ;
while (count < )
{
Console.WriteLine("Print value:{0}", count);
count++;
await Task.Delay();
}
Console.WriteLine("Task Void 结束");
}

接下来写这两句:

 var taskVoid = new Task(Count);
await taskVoid;

哈哈,原本按照其它异步方式去写的时候比如 await HttpClient.GetAsync(); 是非常正常的,程序的逻辑会停在这一句,直到获得结果才会进行下面的语句。但运行 await taskVoid 后,会立即运行下面的语句,这是怎么回事?经过仔细检查发现是因为 Count 方法没有返回值,是 void ,因此必须要加以改造。如果 Count 方法返回值是 Task ,await 才能起效,比如改成这样:

         static void Main(string[] args)
{
Entry();
Console.ReadLine(); } async static Task CountAsync()
{
Console.WriteLine("Task Void 开始");
int count = ;
while (count < )
{
Console.WriteLine("Print value:{0}", count);
count++;
await Task.Delay();
}
Console.WriteLine("Task Void 结束");
} async static void Entry()
{
// 创建一个无参数无返回值的方法
var taskVoid = Task.Factory.StartNew(CountAsync); await taskVoid.Result;
// 创建一个 taskVoid 之后才能运行的方法
var taskContinue = taskVoid.ContinueWith(async (t) =>
{ Console.WriteLine("这是在 TaskVoid 运行之后才能运行的 TaskContinue,Task void 的状态是 {0}", t.Status);
await Task.Delay();
});
;
}

改造后的异步

个人理解:

await 作为语法糖,起作用的对象是 Task ,void 方法返回的不是 Task 自然对之前的写法来讲不起作用。Task 用一个“新线程” 去执行 void 方法,自然立即就“返回”了,但返回并不表示方法结束了,方法内还是按照自己的逻辑去运行了,所以这个时候我只能眼巴巴看着 void 类型的 Count 返回却无力控制它。改成后面的写法之后,改造后的 CountAsync 方法返回的是 Task,意思是告诉上层“我是一个Task”,这个时候 await 就可以起作用了。但直接写 await taskVoid 依旧不能起作用,因为此时 taskVoid 无返回值,也就是立即返回了,所以必须要写成“var taskVoid = Task.Factory.StartNew(CountAsync)” + "await taskVoid.Result"的方式,StartNew 方法会内部新建一个 Task 并返回,这个 Task 的返回值是 CountAsync,而 Result 表示了“我要等待运行 CountAsync 这个异步任务的异步任务的结果返回来”。因此,await 起了作用,执行顺序正确了。

本人学艺不精,对 .Net 内部基本没什么涉猎,如有老鸟看到希望能提出指正意见,谢谢。

.Net 异步随手记(一)的更多相关文章

  1. .Net 异步随手记(三)

    从<.Net 异步随手记(二)>来看,总感觉还差点儿什么,就是对不同情况的处理.比如当一个 Task 完成了后,我想让它继续执行 T1,如果被取消了就去执行 T2,如果...就去执行 T3 ...

  2. .Net 异步随手记(二)

    Task.ContinueWith 这货,和 await 一样有“陷阱”.^^,因为写 ContinueWith 不能直观如人的“过程性”思维,写在 ContinueWith 括号里的部分不一定只在发 ...

  3. [小北De编程手记] : Lesson 05 玩转 xUnit.Net 之 从Assert谈UT框架实践

    这一篇,本文会介绍一下基本的断言概念,但重点会放在企业级单元测试的相关功能上面.下面来跟大家分享一下xUnit.Net的断言,主要涉及到以下内容: 关于断言的概念 xUnit.Net常用的断言 关于单 ...

  4. [小北De编程手记] : Lesson 06 - Selenium For C# 之 流程控制

    无论你是用哪一种自动化测试的驱动框架,当我们构建一个复杂应用程序的自动化测试的时候.都希望构建一个测试流程稳定,维护成本较低的自动化测试.但是,现实往往没有理想丰满.而这一篇,我会为大家讲解我们在使用 ...

  5. JQ深度手记、源码分析

    1.$.extend() 对象继承操作.浅拷贝操作.深拷贝操作(第一个参数:true) var a = { name:'lisan' }; var b = {}; $.extend(b, a); // ...

  6. 袋鼠云研发手记 | 开源·数栈-扩展FlinkSQL实现流与维表的join

    作为一家创新驱动的科技公司,袋鼠云每年研发投入达数千万,公司80%员工都是技术人员,袋鼠云产品家族包括企业级一站式数据中台PaaS数栈.交互式数据可视化大屏开发平台Easy[V]等产品也在迅速迭代.在 ...

  7. NGINX宏观手记

    一.这里的优化主要是指对nginx的配置优化,一般来说nginx配置文件中对优化比较有作用的主要有以下几项: nginx进程数,建议按照cpu数目来指定,一般跟cpu核数相同或为它的倍数. ``` w ...

  8. 【C#】无损转换Image为Icon 【C#】组件发布:MessageTip,轻快型消息提示窗 【C#】给无窗口的进程发送消息 【手记】WebBrowser响应页面中的blank开新窗口及window.close关闭本窗体 【手记】调用Process.EnterDebugMode引发异常:并非所有引用的特权或组都分配给呼叫方 【C#】DataRowState演变备忘

    [C#]无损转换Image为Icon 如题,市面上常见的方法是: var handle = bmp.GetHicon(); //得到图标句柄 return Icon.FromHandle(handle ...

  9. [转]Nodejs开发框架Express4.x开发手记

    Express: ?web application framework for?Node.js? Express 是一个简洁.灵活的 node.js Web 应用开发框架, 它提供一系列强大的特性,帮 ...

随机推荐

  1. 乐视TV2015校园招聘A第二个大的发行量(of中国Academy科学大学站)

    标题叙述性说明:鉴于阵列A,尺寸n,数组元素1至n数字.但是一些数字多次出现.有些数字不出现.请设计算法和程序,统计数据不会出现什么.什么号码多次出现.在O(n)时间复杂度,O(1)在完成它的空间复杂 ...

  2. oracle_安装_win7+64位+Oracle+11g+64位下使用PLSQL+Developer+的解决办法

    1)安装Oracle 11g 64位 2)安装32位的Oracle客户端( instantclient-basic-win32-11.2.0.1.0) 下载instantclient-basic-wi ...

  3. Sql使用视图(简单的视图)适合入门-level

    创建以便从库更好的数据呼叫和一个数据库,以(例如,该209东东库转移205图书馆) 例:209图书馆有不同的库名:数据库(AIS20140417092531电影库)供应商表(t_Supplier ). ...

  4. HDU 1080 Human Gene Functions--DP--(变形最长公共子)

    意甲冠军:该基因序列的两端相匹配,四种不同的核苷酸TCGA有不同的分值匹配.例如T-G比分是-2,它也可以被加入到空格,空洞格并且还具有一个相应的核苷酸匹配分值,求最大比分 分析: 在空气中的困难格的 ...

  5. Linux基础正则表达式:grep,sed

    先说明语系对正则表达式的影响    LANG=C:0,1,2,3,4...A,B,C,D...Z a b c d ... z    LANG=zh_CN:0,1,2,3,4...a A b B c C ...

  6. Php设计模式(三):行为型模式part1

    原文详见:http://www.ucai.cn/blogdetail/7023?mid=1&f=5 可以在线运行查看效果哦! 在上一篇我们讲了结构型模式,结构型模式是讨论类和对象的结构的.总共 ...

  7. Android开展Exception:ActivityNotFoundException: Unable to find explicit activity class

    project出现在一个以上的activity,不AndroidManifest.xml配置,在阅读的时候,你需要知道的配置activity,使用时间或忘记配置.流汗!配置activity后proje ...

  8. 10个实用的PHP正则表达式汇总

    原文 10个实用的PHP正则表达式汇总 正则表达式是程序开发中一个重要的元素,它提供用来描述或匹配文本的字符串,如特定的字符.词或算式等.但在某些情况下,用正则表达式去验证一个字符串比较复杂和费时.本 ...

  9. VS2010类模板修改——添加版权、说明

    VS2010类模板修改——添加版权.说明 最近在学习使用Memcache,就想着用C#代码写一个实现Cache与Memcache以及将来若是能融入Redis切换使用的程序集...不过刚开始写代码,强迫 ...

  10. MySQL 存储过程 经常使用语法

    MySQL 存储过程是从 MySQL 5.0 開始添加的新功能.存储过程的长处有一箩筐.只是最基本的还是运行效率和SQL 代码封装.特别是 SQL 代码封装功能,假设没有存储过程,在外部程序訪问数据库 ...