前言:
C# 5 给我们带来了 async 异步方法,它的出现标志着【次世代】的来临——它可以将多个基于 Task 的操作结合到一起,使代码编写更加直观容易。但 async 也存在额外开销,Task 是引用类型,创建 Task 对象的时候会向堆区申请内存,即使 async 以同步的方式运行,也会有性能开销。到了C# 7,async 方法开始支持返回类Task (task-like)的类型,如 ValueTask ,来减少申请堆内存的次数或在某些情况下完全避免。今天我们主要来了解下如何在c#中借助Task来使用异步,task-like将在下一篇中介绍!
一、async和await的定义
async:作为一个关键字放到函数前面,被async标记不代表该函数就以异步的方式执行,它只是做个标记,让编译器在遇到该标记时对async方法做一些特殊的处理,要有await关键字才说明是异步方法。异步函数也就意味着该函数的执行不会阻塞后面代码的执行
await:意为等待,就是需要等待await后面的函数运行完并且有了返回结果之后,才继续执行下面的代码,这正是同步的效果,await作用就是将异步方法转同步。
await关键字,只能放在async函数里面!!!async函数中可以没有await关键字,此时编译器将向我们显示警告缺少await,但不会显示任何错误。- 一个
async函数中可以有多个awaitasync只需要放在函数的返回类型前的任意位置
二、异步方法的返回类型
异步函数的返回类型只能为: void、Task、Task。
Task: 代表一个返回值T类型的操作。
Task: 代表一个无返回值的操作。
void: 为了和传统的事件处理程序兼容而设计。
private async Task Test_one_async() //这是一个无返回值的异步方法
private async Task<string> Test_two_async() //这是一个返回值类类型是string的异步方法
private async void Test_two_async() //这是一个异步事件处理程序
三、异步方法的适用场景
一般都是比较费时的任务,也就是会阻塞主线程的一些操作,比如获取Http应答,写入文档,读取大文档,保存读取数据库等,将这些方法写入异步函数中,可以达到不阻塞主线程后续方法的目的。
包含异步方法的API有HttpClient, SyndicationClient, StorageFile, StreamWriter, StreamReader, XmlReader, MediaCapture, BitmapEncoder, BitmapDecoder 等
四、异步使用sample
- 在这个例子中,我们将采取两个不相互依赖的方法。Method 1和Method 2不相互依赖,我们是从主方法调用的。在这里,我们可以清楚地看到,方法1和方法2并不是在等待对方完成。
static void Main(string[] args)
{
Console.WriteLine("主线程开始");
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");
}
}
- 我们将创建一个新的方法,作为CallMethod,在这个方法中,我们将调用我们的所有方法,分别为Method 1、Method 2和Method 3。Method 3需要一个参数,即Method 1的返回类型。在这里,await关键字对于等待Method 1任务的完成起着至关重要的作用。
static void Main(string[] args)
{
Console.WriteLine("主线程开始");
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);
}
明白上面的代码,我们就可以在C#代码中使用async 和await关键字来愉快的进行异步编程了。