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

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

做者:依乐祝
原文连接:http://www.javashuo.com/article/p-wkkdrrxi-ck.html编程

写在前面

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

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

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

在这种状况下,异步编程将很是有用。经过使用异步编程,应用程序能够继续进行不依赖于整个任务完成的其余工做。async

在Async 和 await关键字的帮助下,使得异步编程变得很简单,并且咱们将得到传统异步编程的全部好处。异步编程

实例讲解

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

咱们可使用简单的多线程编程并行运行全部方法,可是它会阻塞UI并等待完成全部任务。要解决这个问题,咱们必须在传统编程中编写不少的代码,可是如今咱们有了Async 和 await关键字,那么咱们将经过书写不多的而且简洁的代码来解决这个问题。翻译

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

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并非在等待对方完成。

输出

img

如今来看第二个例子,假设咱们有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)

img
咱们将建立一个新的方法,做为CallMethod,在这个方法中,咱们将调用咱们的全部方法,分别为Method 一、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任务的完成起着相当重要的做用。

输出

img

第三个例子

.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");

输出

img

最后

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

相关文章
相关标签/搜索