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;
}
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:\\";
Task<int> task = ReadFile(filePath);
Console.WriteLine(" Other Work 1");
Console.WriteLine(" Other Work 2");
writeline方法的作用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)
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⽅法来读取⽂本⽂件的内容,并获取⽂本⽂件中总字符的长度。
在中,⽂件包含了太多的字符,因此读取所有字符需要很长时间。
在这⾥,我们使⽤异步编程从⽂件中读取所有内容,所以它不会等待从这个⽅法获得⼀个返回值并执⾏其他代码⾏,但是它必须等待下⾯给出的代码⾏,因为我们使⽤的是等待关键字,我们将对下⾯给出的代码⾏使⽤返回值。
int length = await task;
Console.WriteLine(" Total length: " + length);
随后,将按顺序执⾏其他代码⾏。
Console.WriteLine(" After work 1");
Console.WriteLine(" After work 2");
输出
最后
在这⾥,我们必须了解⾮常重要的⼀点,如果我们没有使⽤await 关键字,那么该⽅法就作为⼀个同步⽅法。编译器将向我们显⽰警告,但不会显⽰任何错误。
像上⾯这种简单的⽅式⼀样,我们可以在C#代码中使⽤async 和await关键字来愉快的进⾏异步编程了。
最后的最后感谢⼤家的阅读!
本⽂⼤部分内容翻译⾃:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论