前言
这是我博客中的第三篇异步编程笔记,前面两篇分别从.NET CORE以及EF CORE的角度去解读C#中的异步编程以及一些默认的规范,如何你需要的特定领域的异步编程知识,请移步谈谈EFCORE中的异步编程规范,以及谈谈.NET CORE中的异步编程。本文将更为系统的讲解C#中异步编程模型概念。
异步编程模型
请看如下代码
-
async Task<int> AccessTheWebAsync()
-
{
-
var client =
new HttpClient();
-
-
client.GetStringAsync(
"https://docs.microsoft.com/dotnet");
-
-
-
DoIndependentWork();
-
-
-
string urlContents =
await getStringTask;
-
-
-
return urlContents.Length;
-
}
从上面的代码块中,可以窥探出异步编程的模型,其具有如下的特征:
以下特征总结了使上一个示例成为异步方法的原因:
-
方法签名包含
async
修饰符。 -
按照约定,异步方法的名称以“Async”后缀结尾。
-
返回类型为下列类型之一:
- 如果你的方法有操作数为 Task<TResult> 类型的返回语句,则为
TResult
。 - 如果你的方法没有返回语句或具有没有操作数的返回语句,则为 Task。
void
:如果要编写异步事件处理程序。- 包含
GetAwaiter
方法的其他任何类型(自 C# 7.0 起)。
- 如果你的方法有操作数为 Task<TResult> 类型的返回语句,则为
- 方法通常包含至少一个
await
表达式,该表达式标记一个点,在该点上,直到等待的异步操作完成方法才能继续。 同时,将方法挂起,并且控制返回到方法的调用方。 本主题的下一节将解释悬挂点发生的情况。
初学者对于C#中异步编程的运行机制,可以不用去深究,先知道什么以及学会如何使用,对于底层的运行机制功力足够深的时候,再去看自然豁然开朗。
几个重要的概念
1.线程与线程
看如下两个图
进程
线程
进程(Process)是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。线程是操作系统分配处理器时间的基本单元,在进程中可以有多个线程同时执行代码。进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程的运行,Windows系统就是利用进程把工作划分为多个独立的区域的。进程可以理解为一个程序的基本边界。是应用程序的一个运行例程,是应用程序的一次动态执行过程。
异步方法旨在成为非阻止操作。 异步方法中的 await
表达式在等待的任务正在运行时不会阻止当前线程。 相反,表达式在继续时注册方法的其余部分并将控制返回到异步方法的调用方。
async
和 await
关键字不会创建其他线程。 因为异步方法不会在其自身线程上运行,因此它不需要多线程。 只有当方法处于活动状态时,该方法将在当前同步上下文中运行并使用线程上的时间。 可以使用 Task.Run 将占用大量 CPU 的工作移到后台线程,但是后台线程不会帮助正在等待结果的进程变为可用状态。
对于异步编程而言,该基于异步的方法优于几乎每个用例中的现有方法。 具体而言,此方法比 BackgroundWorker 类更适用于 I/O 绑定操作,因为此代码更简单且无需防止争用条件。 结合 Task.Run 方法使用时,异步编程比 BackgroundWorker 更适用于 CPU 绑定操作,因为异步编程将运行代码的协调细节与 Task.Run
传输至线程池的工作区分开来。
2.async 和 await
如果使用 async 修饰符将某种方法指定为异步方法,即启用以下两种功能。
-
标记的异步方法可以使用 await 来指定暂停点。
await
运算符通知编译器异步方法:在等待的异步过程完成后才能继续通过该点。 同时,控制返回至异步方法的调用方。异步方法在
await
表达式执行时暂停并不构成方法退出,只会导致finally
代码块不运行。 -
标记的异步方法本身可以通过调用它的方法等待。
3.返回类型和参数
异步方法通常返回 Task 或 Task<TResult>。 在异步方法中,await
运算符应用于通过调用另一个异步方法返回的任务。
如果方法包含指定 Task<TResult> 类型操作数的 return
语句,将 TResult
指定为返回类型。
如果方法不含任何 return 语句或包含不返回操作数的 return 语句,将 Task 用作返回类型。
命名约定
按照约定,返回常规可等待类型的方法(例如 Task
、Task<T>
、ValueTask
和 ValueTask<T>
)应具有以“Async”结束的名称。 启动异步操作但不返回可等待类型的方法不得具有以“Async”结尾的名称,但其开头可以为“Begin”、“Start”或其他表明此方法不返回或引发操作结果的动词。
转载:https://blog.csdn.net/weixin_41372626/article/details/106164844