C# 之 Task、async和 await 、Thread 的简单整理

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来提高任务执行效率。

相关推荐
董先生_ad986ad2 小时前
C# 中的 `lock` 关键字本质
开发语言·c#
爱编程的鱼6 小时前
C# 枚举(Enum)声明与使用详解
java·windows·c#
冰茶_7 小时前
C#中常见的设计模式
java·开发语言·microsoft·设计模式·微软·c#·命令模式
chegan9 小时前
用c#从头写一个AI agent,实现企业内部自然语言数据统计分析(二)-数据结构和代码分析方法
ai·c#·agent
煤烦恼9 小时前
Kafka 命令行操作与 Spark-Streaming 核心编程总结
c#·linq
电商api接口开发10 小时前
ASP.NET MVC 入门指南三
后端·asp.net·mvc
Zhen (Evan) Wang11 小时前
.NET 6 + Dapper + User-Defined Table Type
sqlserver·c#·.net·wpf
[email protected]11 小时前
ASP.NET Core自动事务ActionFilter
后端·asp.net·.netcore
FAREWELL0007512 小时前
C#进阶学习(十四)反射的概念以及关键类Type
开发语言·学习·c#·反射·type
FAREWELL0007512 小时前
C#进阶学习(十三)C#中的预处理器指令
开发语言·学习·c#·预处理指令