异步编程可以提高整个系统的响应速度,但不能提高单次请求的时间。
服务器可以响应更多的请求,每一个请求的总时长基本是不变的。
当一个请求A处理比较耗时的操作,系统就会不等这个请求A,让A自己处理这个耗时操作,而是直接处理下一个请求B。
等这个请求A中耗时的操作处理完了,系统再来接着处理请求A后续的功能。
Async/Await 是一个语法糖,方便写异步编程,其原理是状态机模式编程。
举了一个点菜的例子:你进一个菜馆,服务员A,来接待你到指定座位,然后你开始点菜,由于你点菜比较耗时,服务员A给了你菜单后就去服务其他客户去了。
等你好久点完菜了,然后你再叫服务员把菜单给后厨,但这时服务你的不一定是A,很可能是服务员B。
static async Task Main(string[] args) { Console.WriteLine("第一:"+Thread.CurrentThread.ManagedThreadId); string filePath = @"D:\GitSource\Temp\a.txt"; StringBuilder sb = new StringBuilder(); for (int i = 0; i <10000; i++) { sb.Append("Hello World!"); } Console.WriteLine("第二:" + Thread.CurrentThread.ManagedThreadId); await File.WriteAllTextAsync(filePath, sb.ToString()); Console.WriteLine("第三:" + Thread.CurrentThread.ManagedThreadId); string s = await File.ReadAllTextAsync(filePath); Console.WriteLine("第四:" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine(s); Console.WriteLine("guala"); Console.WriteLine("第五:" + Thread.CurrentThread.ManagedThreadId); Console.ReadKey(); }
可以看到打印出来的线程Id是不一样的。 如果异步处理的时间比较短,也可能一样。
异步方法返回一般是Task类型(无返回值时是Task),当你用await来等时,取到的结果就是T 对象本身。类似于Task.Result
异步不等于多线程
方法标了Async Task就一定是异步方法,但不一定是多线程方法,比如:
Console.WriteLine("异步前:"+Thread.CurrentThread.ManagedThreadId);double result =await GetResultAsync(5);Console.WriteLine("异步后:" + Thread.CurrentThread.ManagedThreadId);Console.ReadKey();async Task GetResultAsync(int input){ Console.WriteLine("异步中:" + Thread.CurrentThread.ManagedThreadId); double result = 0; for (int i = 0; i //{ // double result = 0; // for (int i = 0; i 运行结果:
如果该方法中使用Task来运行:
可以看出是真的多线程执行。
线程休息 ,间隔几秒再做某事,用 await Task.Delay(),不阻塞主线程,异步调用,不要用Thread.Sleep(),这个会阻塞主线程 ,影响web服务的性能
异步调用时注意参数:CancellationToken ,可以传递参数,适时停止操作
static async Task Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); cts.CancelAfter(1000);//1秒之后取消 await GetWebSitHtml("http://www.baidu.com", 10, cts.Token); Console.ReadKey(); } async static Task GetWebSitHtml(string url,int n,CancellationToken cancellationToken) { using (HttpClient client = new HttpClient()) { for (int i = 0; i
GetStringAsync 本身不支持 CancellationToken,可以换一个支持的
async static Task GetWebSitHtml(string url,int n,CancellationToken cancellationToken) { using (HttpClient client = new HttpClient()) { for (int i = 0; i
再有一种是手动停止:比如输入q字母停止:
static async Task Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); GetWebSitHtml("http://www.baidu.com", 100, cts.Token); while (Console.ReadLine() !="q") { } cts.Cancel(); Console.ReadKey(); } async static Task GetWebSitHtml(string url,int n,CancellationToken cancellationToken) { using (HttpClient client = new HttpClient()) { for (int i = 0; i
杨中科讲异步编程,将的很透彻,耐心看完 .NET 6教程,.Net Core 2022视频教程,杨中科主讲_哔哩哔哩_bilibili