众所周知C#提供Async和Await关键字来实现异步编程。在本文中,我们将共同探讨并介绍什么是Async 和 Await,以及如何在C#中使用Async 和 Await。
同样本文的内容也大多是翻译的,只不过加上了自己的理解进行了相关知识点的补充,如果你认为自己的英文水平还不错,大可直接跳转到文章末尾查看原文链接进行阅读。

作者:依乐祝
原文链接:https://www.cnblogs.com/yilezhu/p/10555849.html

写在前面

自从C# 5.0时代引入async和await关键字后,异步编程就变得流行起来。尤其在现在的.NET Core时代,如果你的代码中没有出现async或者await关键字,都会让人感觉到很奇怪。

想象一下当我们在处理UI和按钮单击时,我们需要运行一个长时间运行的方法,比如读取一个大文件或其他需要很长时间的任务,在这种情况下,整个应用程序必须等待这个长时间运行的任务完成才算完成整个任务。

换句话说,如果同步应用程序中的任何进程被阻塞,则整个应用程序将被阻塞,我们的应用程序将停止响应,直到整个任务完成。

在这种情况下,异步编程将非常有用。通过使用异步编程,应用程序可以继续进行不依赖于整个任务完成的其他工作。

在Async 和 await关键字的帮助下,使得异步编程变得很简单,而且我们将获得传统异步编程的所有好处。

实例讲解

假设我们分别使用了两种方法,即Method 1和Method 2,这两种方法不相互依赖,而Method 1需要很长时间才能完成它的任务。在同步编程中,它将执行第一个Method 1,并等待该方法的完成,然后执行Method 2。因此,这将是一个时间密集型的过程,即使这两种方法并不相互依赖。

我们可以使用简单的多线程编程并行运行所有方法,但是它会阻塞UI并等待完成所有任务。要解决这个问题,我们必须在传统编程中编写很多的代码,但是现在我们有了Async 和 await关键字,那么我们将通过书写很少的并且简洁的代码来解决这个问题。

此外,我们还将看到更多的示例,如果任何第三个方法(如Method 3)都依赖于Method 1,那么它将在Wait关键字的帮助下等待Method 1的完成。

Async 和 await是代码标记,它标记代码位置为任务完成后控件应该恢复的位置。

下面让我们举几个例子来更好进行理解吧

C#中Async 和 await关键字的示例

我们将采用控制台应用程序进行演示。

第一个例子

在这个例子中,我们将采取两个不相互依赖的方法。

class Program
{  static void Main(string[] args){
Method1();
Method2();
Console.ReadKey();}  public static async Task Method1(){
await Task.Run(() =>{  for (int i = 0; i < 100; i++){
Console.WriteLine(" Method 1");  }  });  }  public static void Method2(){  for (int i = 0; i < 25; i++){
Console.WriteLine(" Method 2");  }  }
}

在上面给出的代码中,Method 1和Method 2不相互依赖,我们是从主方法调用的。

在这里,我们可以清楚地看到,方法1和方法2并不是在等待对方完成。

输出

现在来看第二个例子,假设我们有Method 3,它依赖于Method 1

第二个例子

在本例中,Method 1将总长度作为整数值返回,我们在Method 3中以长度的形式传递一个参数,它来自Method 1。

在这里,在传递Method 3中的参数之前,我们必须使用AWAIT关键字,为此,我们必须使用调用方法中的async 关键字。

在控制台应用程序的Main方法中,因为不能使用async关键字而不能使用await 关键字,因为它会给出下面给出的错误。(但是如果你使用的是C#7.1及以上的方法是不会有问题的,因为C#7.1及以上的语法支持Mian方法前加async)


我们将创建一个新的方法,作为CallMethod,在这个方法中,我们将调用我们的所有方法,分别为Method 1、Method 2和Method 3。

class Program
{  static void Main(string[] args){
callMethod();
Console.ReadKey();}  public static async void callMethod(){
Task<int> task = Method1();
Method2();int count = await task;
Method3(count);}  public static async Task<int> Method1(){  int count = 0;
await Task.Run(() =>{  for (int i = 0; i < 100; i++){
Console.WriteLine(" Method 1");
count += 1;}  });  return count;}  public static void Method2(){  for (int i = 0; i < 25; i++){
Console.WriteLine(" Method 2");  }  }  public static void Method3(int count){
Console.WriteLine("Total count is " + count);}
}

在上面给出的代码中,Method 3需要一个参数,即Method 1的返回类型。在这里,await关键字对于等待Method 1任务的完成起着至关重要的作用。

输出

第三个例子

.NET Framework4.5中有一些支持API,Windows运行时包含支持异步编程的方法。

在Async 和 await关键字的帮助下,我们可以在实时项目中使用所有这些,以便更快地执行任务。

包含异步方法的API有HttpClient, SyndicationClient, StorageFile, StreamWriter, StreamReader, XmlReader, MediaCapture, BitmapEncoder, BitmapDecoder 等。

在本例中,我们将异步读取大型文本文件中的所有字符,并获取所有字符的总长度。

class Program
{  static void Main(){
Task task = new Task(CallMethod);
task.Start();
task.Wait();
Console.ReadLine();}  static async void CallMethod(){  string filePath = "E:\\sampleFile.txt";
Task<int> task = ReadFile(filePath);Console.WriteLine(" Other Work 1");
Console.WriteLine(" Other Work 2");
Console.WriteLine(" Other Work 3");  int length = await task;
Console.WriteLine(" Total length: " + length);Console.WriteLine(" After work 1");
Console.WriteLine(" After work 2");  }  static async Task<int> ReadFile(string file){  int length = 0;Console.WriteLine(" File reading is stating");  using (StreamReader reader = new StreamReader(file)){  // Reads all characters from the current position to the end of the stream asynchronously   // and returns them as one string.   string s = await reader.ReadToEndAsync();length = s.Length;}
Console.WriteLine(" File reading is completed");  return length;}
}

在上面给出的代码中,我们调用ReadFile方法来读取文本文件的内容,并获取文本文件中总字符的长度。

在sampleText.txt中,文件包含了太多的字符,因此读取所有字符需要很长时间。

在这里,我们使用异步编程从文件中读取所有内容,所以它不会等待从这个方法获得一个返回值并执行其他代码行,但是它必须等待下面给出的代码行,因为我们使用的是等待关键字,我们将对下面给出的代码行使用返回值。

int length = await task;
Console.WriteLine(" Total length: " + length);

随后,将按顺序执行其他代码行。

Console.WriteLine(" After work 1");
Console.WriteLine(" After work 2");

输出

最后

在这里,我们必须了解非常重要的一点,如果我们没有使用await 关键字,那么该方法就作为一个同步方法。编译器将向我们显示警告,但不会显示任何错误。
像上面这种简单的方式一样,我们可以在C#代码中使用async 和await关键字来愉快的进行异步编程了。
最后的最后感谢大家的阅读!
本文大部分内容翻译自:https://www.c-sharpcorner.com/article/async-and-await-in-c-sharp/

C# 中的Async 和 Await 的用法详解相关推荐

  1. 【转载】 C# 中的Async 和 Await 的用法详解

    众所周知C#提供Async和Await关键字来实现异步编程.在本文中,我们将共同探讨并介绍什么是Async 和 Await,以及如何在C#中使用Async 和 Await. 同样本文的内容也大多是翻译 ...

  2. async 与 await 的用法详解

    文章出自个人博客https://knightyun.github.io/2019/08/02/js-async-await,转载请申明 async 概念 用于声明异步函数,返回值为一个 Promise ...

  3. oracle中的exists 和 not exists 用法详解

    from:http://blog.sina.com.cn/s/blog_601d1ce30100cyrb.html oracle中的exists 和 not exists 用法详解 (2009-05- ...

  4. python多个strip_python 格式化多个Python3中strip()、lstrip()、rstrip()用法详解

    Python中有三个去除头尾字符.空白符的函数,它们依次为: strip: 用来去除头尾字符.空白符(包括n.r.t.' ',即:换行.回车.制表符.空格) lstrip:用来去除开头字符.空白符(包 ...

  5. linux cp -r 参数,Linux系统中cp命令的参数及用法详解

    Linux系统中cp命令主要是用来复制文件或者目录.下面由学习啦小编为大家整理了Linux系统中cp命令的参数及用法详解的相关知识,希望对大家有帮助! Linux系统中cp命令的参数及用法详解:参数说 ...

  6. linux 移动剪切命令,Linux中vi的复制命令的用法详解

    在Linux系统中,使用VI编辑的时候经常用到的操作就是复制粘贴,那么下面由学习啦小编为大家整理了linux中vi的复制命令的用法详解的相关知识,希望对大家有帮助! Linux中vi的复制命令的用法详 ...

  7. python中rstrip用法_浅谈Python3中strip()、lstrip()、rstrip()用法详解

    简单来说,三种方法是为了删除字符串中不同位置的指定字符.其中,strip()用于去除字符串的首尾字符,同理,lstrip()用于去除左边的字符,rstrip()用于去除右边的字符 Python中有三个 ...

  8. linux中替换命令详解,linux中sed命令字符串替换的用法详解

    Linux系统中sed命令可以将字符串批量替换,省去了很多麻烦,下面由学习啦小编为大家整理了linux系统中sed命令字符串替换的用法详解,希望对大家有帮助! linux中sed命令字符串替换的用法详 ...

  9. java return返回值_java中关于return返回值的用法详解

    我们输入一个条件时,系统就会对这个条件进行判断,然后给出一个返回时的结论,我们把这个结果看做是返回值.在java里可以使用return语句来进行返回,从字面意思就能很好的理解它的用法了.下面我们就re ...

最新文章

  1. android中方法调用super(..)的相关知识
  2. 五年循环期限已到,我们又要步入“AI寒冬”了吗?
  3. 基于Flink SQL构建流批一体实时数仓
  4. Jetson Xavier(Ubuntu18.04)安装固态硬盘并挂载到/home区下
  5. java多线程------实现Runnable接口创建多进程,实现资源共享
  6. 网页中设定表格边框的厚度的属性_网页试题
  7. 博弈论入门 HDU 1850
  8. Spring思维导图,让spring不再难懂(一)
  9. 离散数学图论旅行规划问题_《图论及其应用》(一)
  10. Oracle中如何查询一个表的所有字段名和数据类型
  11. php.h: No such file or directory
  12. python 内存管理
  13. Linux查看磁盘块大小
  14. 米家扫地机器人怎么加水_时隔两年半终于更新 贵了500元的小米米家扫地机器人1S值得买吗?...
  15. LeetCode 6罗马数字转整数
  16. 【C++从青铜到王者】第二十七篇:特殊类设计
  17. 32位汇编第三讲,RadAsm,IDE的配置和使用,以及汇编代码注入方式
  18. 计算机右键管理快捷键,鼠标右键菜单管理
  19. cocos2d-x csb特效文件显示
  20. Unity在URP管线下使用TriLib插件加载模型材质不正确的问题

热门文章

  1. Vue中数组赋值问题
  2. shell 学习之正则、别名以及管道重定向
  3. AngularJs在IE10,11中的一个坑。
  4. Open Sans字体兼容问题解决办法[font-face]
  5. Xampp安装时需注意的事项
  6. 在线转flv+flash在线录制视频
  7. DevOps 的发展史
  8. 23 张图详解路由协议:计算机网络的核心技术
  9. 京东超大规模联邦学习探索实践
  10. 拼多多,一面,i++ 是线程安全的吗?一脸蒙逼