C#扫盲篇(四):.NET Core 的异步编程-只讲干货(async,await,Task)
using System;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleTest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(ThreadID() + " =》主线程启动");
MethodAsync();//调用异步方法
Console.WriteLine(ThreadID() + " =》主线程继续执行");
Console.WriteLine(ThreadID() + " =》主线程结束 END");
Console.Read();
}
static async void MethodAsync()
{
Console.WriteLine(ThreadID() + " =》MethodAsync方法开始执行");
string str = await DoSomething();//等待GetString执行完成
Console.WriteLine(ThreadID() + " =》MethodAsync方法执行结束");
}
static Task<string> DoSomething()
{
Console.WriteLine(ThreadID() + " =》DoSomething方法开始执行");
return Task<string>.Run(() =>
{
Thread.Sleep(4000);//导步线程 处理耗时任务
Console.WriteLine(ThreadID() + " =》DoSomething方法结束执行");
return "GetString的返回值";
});
}
static string ThreadID()
{
return Thread.CurrentThread.ManagedThreadId.ToString();
}
}
}
以上代码的执行结果如图:
这个例子非常的经典,是曾经上学时老师给我们的实例,用来理解这几个关键词特别好。
看完代码的执行顺序,以下对新手,包括自己曾经的疑问做一些简明扼要的解释,希望一两句话能让大家马上知道,不至于被网上各种文章绕晕。
疑问一:await会阻塞当前线程,等异步线程干完活了再跑?
不会阻塞。当前线程会一直跑进异步方法里,直到遇到要新开一个线程干活时就返回继续跑。此时,新线程在那里干活,主线程干完活就忙其他事去了。新线程干完活,回来await的地方把接下来的活继续干了。
疑问二:async+await 和同步执行有什么好处,都是要一个线程干活,一条龙干到底不好吗,非得自己干到一半交给另一个线程去干,别人干活不用开销吗?
这个问题的关键就是有些IO事情真的不需要CPU派一个线程去干,去了也干不了。比如读写文件,以往同步方法时,派一个线程去读写点东西的时候,这个线程肯定是等在那的,读写这个事情是硬盘去做的,线程就是个使者,告诉硬盘要做哪些事就行,硬盘干完活就告诉线程,线程拿着结果开心地继续干下面的活。那异步就是线程通知硬盘去读写后自己就回去该干嘛干嘛去,不必等在硬盘家门口等消息。硬盘读写的时候,这个线程是非阻塞的,可以干其他活,提高效率。硬盘读写完,会通知CPU,叫他派一个线程来拿结果,(如果框架是单线程的,那还是这个线程过来)这个线程拿到结果后会继续执行之前那个线程未干完的活,至于上下文信息,底层会交代好,不在这里讨论,太深。这个IO事情有很多,比如访问数据库,请求网络等。
往期精彩:
- C#扫盲篇(一):反射机制–情真意切的说
- C#扫盲篇(二)依赖倒置•控制反转•依赖注入•面向接口编程–满腹经纶的说
- 利用COM组件实现对WORD书签各种操作大全,看这一篇就够了
- Entity Framework 更新失败,调试后发现是AsNoTracking的原因
- “生如蝼蚁,当立鸿鹄之志”|2020年终总结
首发自:【程序员不帅哥 】公众号
原文链接:https://mp.weixin.qq.com/s/P2oN-2au3x5oTbzlrC5WYg
扫码关注,更多精彩内容及时获取,一起提高,一起加油