对于async和await的使用方式、作用效果不怎么理解 ?没关系,初步看这篇就够了
结论
同步还是异步,区别如下:
- 同步:你使用 await 修饰符去调用一个异步(async)方法(是异步方法,不过是阻塞式的,可简单理解为同步);
- 异步:你获取异步方法返回的 Task,就是异步(后文有代码示例);
- 可以实现多任务执行顺序执行且不阻塞。
概述
async(C# 参考)
async 是“异步”的简写,使用 async 修饰符可将方法、lambda 表达式或匿名方法指定为异步。
如果对方法或表达式使用此修饰符,则其称为异步方法 。
如下示例定义了一个名为 ExampleMethodAsync
的异步方法:
public async Task<int> ExampleMethodAsync()
{
//...
}
await(C# 参考)
await 运算符暂停对其所属的 async 方法的求值,直到其操作数表示的异步操作完成。
异步操作完成后,await 运算符将返回操作的结果(如果有)。
当 await 运算符应用到表示已完成操作的操作数时,它将立即返回操作的结果,而不会暂停其所属的方法。
await 运算符不会阻止计算异步方法的线程。
当 await 运算符暂停其所属的异步方法时,控件将返回到方法的调用方。
官网说的话是不是听不明白?没关系,你就理解为添加了await 修饰符后,必须要等调用返回后才能继续执行下一步。
如下示例:
public async Task<int> ExampleMethodAsync()
{
//...
//这添加了await,执行到这里需要等待MethodAwiat方法执行完成后才会往下继续执行。
int result = await MethodAwiat();
//... }
public async Task<int> MethodAwiat()
{
//...
}
作用及基本用法
await和async可以简化我们异步编程,也可以让我们以一种类似同步编程的方式来进行异步编程。
另外当我们需要不阻塞主线程异步执行,但又要有顺序的执行相关代码的时候,await/async就可以排上用场。
基本用法如下示例:
/// <summary>
/// 可异步可同步
/// </summary>
/// <returns></returns>
public async Task<string> TestAsync()
{
Thread.Sleep(3000);
Task<string> task = new Task<string>(() =>
{
return "主程序返回后我还在执行数据:我是复杂的异步执行的方法,不阻碍主程序执行。。。。。";
});
task.Start();
return await task;
} // await 使得任务同步
public async void T1()
{
// 使用 await 关键字,代表等待执行完成,同步
string time = await TestAsync();
Console.WriteLine(time);
Console.WriteLine("执行完毕");
} // 直接获得返回的 Task,实现异步
public void T2()
{
// 获取 Task 任务对象,后面的逻辑过程可以弄成异步
Task<string> task = TestAsync(); // 这里可以处理其它事情,处理完毕后,再获取执行结果
Console.WriteLine("执行完毕"); Console.WriteLine(task.Result);
}
实现多任务顺序执行且不阻塞
以微软文档的做早餐的案例加以简化来讲解 【使用Async和Await可以实现多任务顺序执行且不阻塞】。
主线任务任务:倒橙汁 -> 烤面包 -> 煎培根 -> 煎鸡蛋 -> 倒咖啡。
1.同步执行
我们任务逐步顺序执行如下,耗时:17064毫秒(17.064秒):
using Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter;
using System;
using System.Diagnostics;
using System.Threading; namespace ConsoleApp1
{
class Program
{ static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
PourOJ();
PourCoffee();
ToastBread();
FryBacon();
FryEggs();
Console.WriteLine("早餐已经做完!");
stopwatch.Stop();
Console.WriteLine($"做早餐总计耗时:{stopwatch.ElapsedMilliseconds}");
Console.ReadLine(); } //倒橙汁
private static void PourOJ()
{
Thread.Sleep(1000);
Console.WriteLine("倒一杯橙汁");
} //烤面包
private static void ToastBread()
{
Console.WriteLine("开始烤面包");
Thread.Sleep(3000);
Console.WriteLine("烤面包好了"); } //煎培根
private static void FryBacon()
{
Console.WriteLine("开始煎培根");
Thread.Sleep(6000);
Console.WriteLine("培根煎好了");
}
//煎鸡蛋
private static void FryEggs()
{
Console.WriteLine("开始煎鸡蛋");
Thread.Sleep(6000);
Console.WriteLine("鸡蛋好了");
} //倒咖啡
private static void PourCoffee()
{
Thread.Sleep(1000);
Console.WriteLine("倒咖啡");
}
}
}
2.并行执行
如果此时我们每一项任务都有一个单独的人去完成,将会缩短时间将近3倍(当然不能单纯的用时间量化他),
如下,耗时6041毫秒(6.041秒):
using Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleApp1
{
class Program
{ static void Main(string[] args)
{
Test();
Console.ReadLine(); } private static void Test()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
List<Task> tasks = new List<Task>() { PourOJ(), ToastBread(), FryBacon(), FryEggs(), PourCoffee() };
Task.WhenAll(tasks).ContinueWith((t) =>
{
Console.WriteLine("早餐已经做完!");
stopwatch.Stop();
Console.WriteLine($"做早餐总计耗时:{stopwatch.ElapsedMilliseconds}");
});
} //倒橙汁
private static async Task PourOJ()
{
await Task.Delay(1000);
Console.WriteLine("倒一杯橙汁");
} //烤面包
private static async Task ToastBread()
{
Console.WriteLine("开始烤面包");
await Task.Delay(3000);
Console.WriteLine("烤面包好了"); } //煎培根
private static async Task FryBacon()
{
Console.WriteLine("开始煎培根");
await Task.Delay(6000);
Console.WriteLine("培根煎好了");
}
//煎鸡蛋
private static async Task FryEggs()
{
Console.WriteLine("开始煎鸡蛋");
await Task.Delay(6000);
Console.WriteLine("鸡蛋好了");
} //倒咖啡
private static async Task PourCoffee()
{
await Task.Delay(1000);
Console.WriteLine("倒咖啡");
}
}
}
3.并行且可指定顺序执行
但是我们不可能每次做早餐都有那么多人同时做,
需求变更:如果现在要求,先倒橙汁,然后倒咖啡,其余的操作并行执行,应该如何操作呢?
只需将以上案例的主线程Test 方法修改如下,其他的不变,耗时8073毫秒(8.073秒):
private static async void Test()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
await PourOJ(); //倒橙汁
await PourCoffee(); //然后倒咖啡
List<Task> tasks = new List<Task>() { ToastBread(), FryBacon(), FryEggs() };//子任务List
await Task.WhenAll(tasks); //其余的并行操作
Console.WriteLine("早餐已经做完!");
stopwatch.Stop();
Console.WriteLine($"做早餐总计耗时:{stopwatch.ElapsedMilliseconds}");
}
总结
我们发现,用好了async和await确实很节省时间。
大家可以想想怎么优雅的在异步里面开多线程(多主线程多子线程)最节省时间。
参考文献
喜欢就点赞加关注。
欢迎关注订阅微信公众号【熊泽有话说】,更多好玩易学知识等你来取
作者:熊泽-学习中的苦与乐
公众号:熊泽有话说
QQ群:711838388
出处:https://www.cnblogs.com/xiongze520/p/16976940.html
您可以随意转载、摘录,但请在文章内注明作者和原文链接。
对于async和await的使用方式、作用效果不怎么理解 ?没关系,初步看这篇就够了的更多相关文章
- 简单的试了试async和await处理异步的方式
今天无意中就来试了试,感觉这个新的方法还是非常行的通的,接下来我们上代码 这段代码想都不用想输出顺序肯定是//null null 233,当然出现这个问题还是因为它是同步,接下来我们就进行异步方式来处 ...
- jmeter实现接口关联的两种方式:正则表达式提取器和json提取器看这篇就够了
一.前言在开展接口测试或者是接口面试的过程中,我们会发现很多接口需要依赖前面的接口,需要我们动态从前面的接口返回中提取数据,也就是我们通常说的关联. 关联通俗来讲就是把上一次请求的返回内容中的部分截取 ...
- Async 与 Await 关键字研究
1 Aynsc 和 Await 关键字的研究 在 .NET 4.0 以后,基于 Task 的异步编程模式大行其道,因其大大简化了异步编程所带来的大量代码工作而深受编程人员的欢迎,如果你曾 ...
- 为什么我们要使用Async、Await关键字
前不久,在工作中由于默认(xihuan)使用Async.Await关键字受到了很多质问,所以由此引发这篇博文“为什么我们要用Async/Await关键字”,请听下面分解: Async/Await关键字 ...
- C#多线程编程(2)-- async,await基本用法
上一章我简单介绍了异步编程的基本方法,推荐使用的方式是Task.Task是对线程池的封装,并且可以对Task使用async和await关键字.这两个关键字的使用非常简单,那么这两个关键字究竟起什么作用 ...
- promise以及async、await学习总结
Promise/async.await帮我们解决了什么 它给我们提供了一种新的异步编程解决方案,同时避免了困扰已久的回调地狱 // 异步的处理可能会产生这样的回调地狱(第二个异步操作和第一个异步的结果 ...
- 反爬虫:利用ASP.NET MVC的Filter和缓存(入坑出坑) C#中缓存的使用 C#操作redis WPF 控件库——可拖动选项卡的TabControl 【Bootstrap系列】详解Bootstrap-table AutoFac event 和delegate的分别 常见的异步方式async 和 await C# Task用法 c#源码的执行过程
反爬虫:利用ASP.NET MVC的Filter和缓存(入坑出坑) 背景介绍: 为了平衡社区成员的贡献和索取,一起帮引入了帮帮币.当用户积分(帮帮点)达到一定数额之后,就会“掉落”一定数量的“帮帮 ...
- 常见的异步方式async 和 await
之前研究过c#的async和await关键字,幕后干了什么,但是不知道为什么找不到相关资料了.现在重新研究一遍,顺便记录下来,方便以后查阅. 基础知识 async 关键字标注一个方法,该方法返回值是一 ...
- [译] C# 5.0 中的 Async 和 Await (整理中...)
C# 5.0 中的 Async 和 Await [博主]反骨仔 [本文]http://www.cnblogs.com/liqingwen/p/6069062.html 伴随着 .NET 4.5 和 V ...
- 探索c#之Async、Await剖析
阅读目录: 基本介绍 基本原理剖析 内部实现剖析 重点注意的地方 总结 基本介绍 Async.Await是net4.x新增的异步编程方式,其目的是为了简化异步程序编写,和之前APM方式简单对比如下. ...
随机推荐
- Beats:在 Beats 中实现动态 pipeline
转载自:https://blog.csdn.net/UbuntuTouch/article/details/107127197 在我们今天的练习中,我们将使用 Metricbeat 来同时监控 kib ...
- 中国数字化是怎么转型成新范式TOP 50的?
我不大认可"中国数字化转型成新范式TOP 50"的,确切的说,照着"中国数字化转型新范式TOP 50"做转型,大概率失败,对中国企业数字化转型的帮助甚微 ,尤其 ...
- 使用SqlDataReader对象从数据库中检索只读的数据。
SqlDataReader对象每次从查询结果中读取一行到内存中,对于sql数据库,如果只需要顺序读取,可以优先选择SqlDataReader,其对数据库的读取速度非常快. 调用SqlDataReade ...
- 220702 T1 玩具 (图的同构,全排列判定)
[题目描述] Tom和Jerry各有一个玩具,每个玩具都是由M根绳子连接到N个球上制成的. 在Tom的玩具中,球的编号为1,-,N,第i条绳子将球Ai和Bi连接起来. 类似地,在Jerry的玩具中,球 ...
- swoole学习笔记
一.服务端 0. swoole常用的配置项: daemonize = true 守护进程化 worker_num #swoole配置参数 设置启动的Worker进程数: 如 1 个请求耗时 100ms ...
- Landau-Vishkin
基础算法 假设我们有两个字符串:,每个字符串由A C G T四个字母组成. 在两个字符串上,都有三种可能的编辑操作(突变): 删除某个字符 在某个位置插入字符 改变某个字符 每一个编辑操作都有惩罚值. ...
- 题解 P4058 [Code+#1]木材
前言 这什么题啊,不就是个二分答案我从65到100都经历了一遍--(瞬间气哭) \(\sf {Solution}\) 题目理解起来不难的,大意就懒得写了. 一眼二分答案. 此题属于在形如 \(\{0, ...
- Istio(九):istio安全之授权
目录 一.模块概览 二.系统环境 三.istio授权 3.1 istio授权 3.2 来源 3.3 操作 3.4 条件 四.实战:授权(访问控制) 4.1 访问控制 4.2 清理 一.模块概览 在Ku ...
- 微信小程序——悬浮按钮
关键: position: fixed; wxml: <navigator url="/pages/issue/index"><image class='i ...
- Java多线程-ThreadPool线程池-2(四)
线程池是个神器,用得好会非常地方便.本来觉得线程池的构造器有些复杂,即使讲清楚了对今后的用处可能也不太大,因为有一些Java定义好的线程池可以直接使用.但是(凡事总有个但是),还是觉得讲一讲可能跟有助 ...