浅谈C#中的Async和Await的用法详解

 更新时间:2020年6月25日 10:37  点击:2370

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

同样本文的内容也大多是翻译的,只不过加上了自己的理解进行了相关知识点的补充,如果你认为自己的英文水平还不错,大可直接跳转到文章末尾查看原文链接进行阅读。

写在前面

自从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关键字来愉快的进行异步编程了。

最后的最后感谢大家的阅读!希望对大家的学习有所帮助,也希望大家多多支持猪先飞。

[!--infotagslink--]

相关文章

  • C#实现简单的登录界面

    我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
  • 浅谈C# 字段和属性

    这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
  • C#中截取字符串的的基本方法详解

    这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
  • C#实现简单的Http请求实例

    这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
  • C#连接SQL数据库和查询数据功能的操作技巧

    本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
  • C#中new的几种用法详解

    本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
  • 使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)

    这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#开发Windows窗体应用程序的简单操作步骤

    这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
  • C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
  • C#和JavaScript实现交互的方法

    最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • 轻松学习C#的基础入门

    轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
  • C#变量命名规则小结

    本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
  • C#绘制曲线图的方法

    这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
  • c#自带缓存使用方法 c#移除清理缓存

    这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25
  • c#中(&&,||)与(&,|)的区别详解

    这篇文章主要介绍了c#中(&&,||)与(&,|)的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
  • 经典实例讲解C#递归算法

    这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
  • C#学习笔记- 随机函数Random()的用法详解

    下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#中list用法实例

    这篇文章主要介绍了C#中list用法,结合实例形式分析了C#中list排序、运算、转换等常见操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25