1、异步方法(async/await)
在 C# 5.0 中出现的 async 和 await ,让异步编程变得更简单。
此方法利用了 .NET Framework 4.5 及更高版本、.NET Core 和 Windows 运行时中的异步支持。
编译器可执行开发人员曾进行的高难度工作,且应用程序保留了一个类似于同步代码的逻辑结构。
async 用在方法定义前面,await只能写在带有async标记的方法中。
注意await异步等待的地方,await后面的代码和前面的代码执行的线程可能不一样
async关键字创建了一个状态机,类似yield return 语句;await会解除当前线程的阻塞,完成其他任务
这里实现同步异步读取文件内容的方式。
我们可以看到异步读取代码和同步读取代码基本一致。async/await让异步编码变得更简单,我们可以像写同步代码一样去写异步代码。
注意一个小问题:异步方法中方法签名返回值为Task,代码中的返回值为T。
代码中GetContentAsync的签名返回值为Task,而代码中返回值为string。牢记这一细节对我们分析异步代码很有帮助。
异步方法签名的返回值有以下三种:
① Task:如果调用方法想通过调用异步方法获取一个T类型的返回值,那么签名必须为Task;
② Task:如果调用方法不想通过异步方法获取一个值,仅仅想追踪异步方法的执行状态,那么我们可以设置异步方法签名的返回值为Task;
③ void:如果调用方法仅仅只是调用一下异步方法,不和异步方法做其他交互,我们可以设置异步方法签名的返回值为void,这种形式也叫做“调用并忘记”。
参考代码如下
static void Main(string[] args)
{
//Console.WriteLine(" Environment.CurrentDirectory "+ Environment.CurrentDirectory);
string content = GetContentAsync(Environment.CurrentDirectory + @"/test.txt").Result;
//调用同步方法
//string content = GetContent(Environment.CurrentDirectory + @"/test.txt");
Console.WriteLine(content);
Console.ReadKey();
}
/// <summary>
/// 异步读取文件内容
/// </summary>
/// <param name="filename"></param>
/// <returns></returns>
async static Task<string> GetContentAsync(string filename)
{
FileStream fs = new FileStream(filename, FileMode.Open);
var bytes = new byte[fs.Length];
//ReadAync方法异步读取内容,不阻塞线程
Console.WriteLine("开始读取文件");
int len = await fs.ReadAsync(bytes, 0, bytes.Length);
string result = Encoding.UTF8.GetString(bytes);
return result;
}
/// <summary>
/// 同步读取文件内容
/// </summary>
/// <param name="filename"></param>
/// <returns></returns>
static string GetContent(string filename)
{
FileStream fs = new FileStream(filename, FileMode.Open);
var bytes = new byte[fs.Length];
//Read方法同步读取内容,阻塞线程
int len = fs.Read(bytes, 0, bytes.Length);
string result = Encoding.UTF8.GetString(bytes);
return result;
}
2、Task、async和 await 、Thread 简单小结
最后我们简单记住一些特性,就可以有个较好的理解他们了:
1)async/await是基于Task的
2)而Task是对ThreadPool的封装改进,主要是为了更有效的控制线程池中的线程(ThreadPool中的线程,我们很难通过代码控制其执行顺序,任务延续和取消等等);
3)ThreadPool基于Thread的,主要目的是减少Thread创建数量和管理Thread的成本。
4)async/await Task是C#中更先进的,也是微软大力推广的特性
5)我们在开发中可以尝试使用Task来替代Thread/ThreadPool,处理本地IO和网络IO任务是尽量使用async/await来提高任务执行效率。