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

众所周知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关键字来愉快的进行异步编程了。

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

(0)

相关推荐

  • 说说C#的async和await的具体用法

    C# 5.0中引入了async 和 await.这两个关键字可以让你更方便的写出异步代码. 看个例子: public class MyClass { public MyClass() { DisplayValue(); //这里不会阻塞 System.Diagnostics.Debug.WriteLine("MyClass() End."); } public Task<double> GetValueAsync(double num1, double num2) { re

  • 详解C#中的Async和Await用法

    这篇文章由Filip Ekberg为DNC杂志编写. 自跟随着.NET 4.5 及Visual Studio 2012的C# 5.0起,我们能够使用涉及到async和await关键字的新的异步模式.有很多不同观点认为,比起以前我们看到的,它的可读性和可用性是否更为突出.我们将通过一个例子来看下它跟现在的怎么不同. 线性代码vs非线性代码 大部分的软件工程师都习惯用一种线性的方式去编程,至少这是他们开始职业生涯时就被这样教导.当一个程序使用线性方式去编写,这意味着它的源代码读起来有的像Figure

  • 详解C#中 Thread,Task,Async/Await,IAsyncResult的那些事儿

    说起异步,Thread,Task,async/await,IAsyncResult 这些东西肯定是绕不开的,今天就来依次聊聊他们 1.线程(Thread) 多线程的意义在于一个应用程序中,有多个执行部分可以同时执行:对于比较耗时的操作(例如io,数据库操作),或者等待响应(如WCF通信)的操作,可以单独开启后台线程来执行,这样主线程就不会阻塞,可以继续往下执行:等到后台线程执行完毕,再通知主线程,然后做出对应操作! 在C#中开启新线程比较简单 static void Main(string[]

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

    众所周知C#提供Async和Await关键字来实现异步编程.在本文中,我们将共同探讨并介绍什么是Async 和 Await,以及如何在C#中使用Async 和 Await. 同样本文的内容也大多是翻译的,只不过加上了自己的理解进行了相关知识点的补充,如果你认为自己的英文水平还不错,大可直接跳转到文章末尾查看原文链接进行阅读. 写在前面 自从C# 5.0时代引入async和await关键字后,异步编程就变得流行起来.尤其在现在的.NET Core时代,如果你的代码中没有出现async或者await

  • 浅谈Python3中strip()、lstrip()、rstrip()用法详解

    简单来说,三种方法是为了删除字符串中不同位置的指定字符.其中,strip()用于去除字符串的首尾字符,同理,lstrip()用于去除左边的字符,rstrip()用于去除右边的字符 Python中有三个去除头尾字符.空白符的函数,它们依次为: strip: 用来去除头尾字符.空白符(包括\n.\r.\t.' ',即:换行.回车.制表符.空格) lstrip:用来去除开头字符.空白符(包括\n.\r.\t.' ',即:换行.回车.制表符.空格) rstrip:用来去除结尾字符.空白符(包括\n.\r

  • 浅谈多线程中的锁的几种用法总结(必看)

    一.ReentrantLock package com.ietree.basicskill.mutilthread.lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * Created by Administrator on 2017/5/17. */ public class UseReentrantLock { private Lock lock

  • 浅谈keras中的目标函数和优化函数MSE用法

    mean_squared_error / mse 均方误差,常用的目标函数,公式为((y_pred-y_true)**2).mean() model = Sequential() model.add(Dense(64, init='uniform', input_dim=10)) model.add(Activation('tanh')) model.add(Activation('softmax')) sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, ne

  • 浅谈js中的attributes和Attribute的用法与区别

    一:Attribute的几种用法和含义(attributes和Attribute都是用来操作属性的) getAttribute:获取某一个属性的值: setAttribute:建立一个属性,并同时给属性捆绑一个值: createAttribute:仅建立一个属性: removeAttribute:删除一个属性: getAttributeNode:获取一个节点作为对象: setAttributeNode:建立一个节点: removeAttributeNode:删除一个节点: 1.getAttrib

  • 浅谈python3打包与拆包在函数的应用详解

    1.序列(拆包) *用作序列拆包:*可对字符串.列表.集合.元组.字典.数字元素等序列进行拆包 print(*(1,2,3,4,5,6)) #1 2 3 4 5 6 print(*[1,2,3,4,5,6]) #1 2 3 4 5 6 序列拆包赋值: 注意:*变量 不能在第一个位置,否则会报错 a, b, *c = 0, 1, 2, 3 #获取剩余部分 a, *b, c = 0, 1, 2, 3 #获取中间部分 a, b, *c = 0, 1 a, *b, c = 0, 1 优先对位置变量赋值,

  • JS中正则表达式全局匹配模式 /g用法详解

    本文章来详细介绍js中正则表达式的全局匹配模式 /g用法,代码如下: var str = "123#abc"; var re = /abc/ig; console.log(re.test(str)); //输出ture console.log(re.test(str)); //输出false console.log(re.test(str)); //输出ture console.log(re.test(str)); //输出false 在创建正则表达式对象时如果使用了"g&q

  • Python 中 Virtualenv 和 pip 的简单用法详解

    本文介绍了Python 中 Virtualenv 和 pip 的简单用法详解,分享给大家,具体如下: 0X00 安装环境 我们在 Python 开发和学习过程中需要用到各种库,然后在各个不同的项目和作品里可能用的版本还不一样,正因为有这种问题的存在才催生了virtualenv的诞生.virtualenv 可以在电脑上创建一个虚拟环境,可以针对每一个项目创建一个虚拟环境,这样就不用担心各个不同的项目用不同版本的库的时候出现的冲突了. 下面的内容只适用于 Linux/OSX,未经 Windows 环

  • 有关C++中随机函数rand() 和srand() 的用法详解

    一.rand() 函数名:   rand 功   能:   随机数发生器 用   法:   int rand(void); 所在头文件: stdlib.h 函数说明 : rand()的内部实现是用线性同余法做的,它不是真的随机数,因其周期特别长,故在一定 的范围里可看成是随机的. rand()返回一随机数值的范围在0至RAND_MAX 间.RAND_MAX的范围最少是在32767之间(int).用 unsigned int 双字节是65535,四字节是4294967295的整数范围.0~RAND

  • Java中volatile关键字的作用与用法详解

    volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以重获生机. volatile 关键字作用是,使系统中所有线程对该关键字修饰的变量共享可见,可以禁止线程的工作内存对volatile修饰的变量进行缓存. volatile 2个使用场景: 1.可见性:Java提供了volatile关键字来保证可见性. 当一个共享变量被volatile修饰时,它会保证修

随机推荐