究竟什么应该称为异步方法?应该使用什么标准来调用异步方法?其他术语似乎很清楚,但让我们重复一下,以便我们可以进一步使用它来尝试定义异步方法的概念。
回忆相关概念
有一个异步方法调用(AMI)的概念——
在等待被调用代码完成时调用站点未被阻塞。相反,当回复到达时,调用线程会收到通知。
此外,调用这个词可以更改为调用或执行。
有一个异步的概念,但在编程中它似乎几乎可以与 AMI ( 1 ) 互换使用——
执行一个操作而不等待这个处理完成,执行的结果可以稍后处理。
他们经常举一个例子,用一个烧开的水壶来解释它是什么。
让我们寻找一个异步方法的定义,暂时忘记我们是如何想象它的,以便客观。
- 来源一 - async 关键字的文档-
使用 async 修饰符指定方法、lambda 表达式或匿名方法是异步的。如果在方法或表达式上使用此修饰符,它被称为异步方法。
可以翻译为:如果在方法或表达式中使用此修饰符,则称为异步方法。很明显,并非每个使用异步的方法都必须包含 AMI 或与现实中的异步相关的东西。
- 另一方面,有这样一个来源2:
异步方法是我们调用以启动冗长操作的方法。该方法应该执行启动操作所需的操作并“非常快速地”返回,以便没有处理延迟。
如果您的线程告诉该方法它需要完成工作,并且该方法说“好的,我会这样做,完成后我会打电话给您”,则该方法是异步的
这向我们暗示,在异步方法的定义中应该有一些关于 AMI 的内容,我们在上面回忆过。
- 甚至在旧 Dock 中的同一个 microsoftware 中(在 async 关键字出现之前),您也可以找到该术语的以下用法(3):
如果异步方法遇到未处理的异常,...
所以看起来这样的概念甚至在 async 关键字之前就已经存在,但也许随着它的出现,新的含义出现了纯粹与语言的语法有关。
- ...
不幸的是,研究这些来源需要很长时间,所以我有机会补充那些将回答这个问题的人。
试图从来源中找到定义。
根据所研究的来源,我想到了定义异步方法的哪些选项:
- 这是声明时带有 async 关键字的方法。例子:
async void SimpleAsync() {}
- 它是一种可用于非阻塞调用的方法。例子:
async void DelayAsync() { Task.Delay(1); } //Task.Delay асинхронный, так его можно использовать для AMI. Прям тут и используют.
async void Delay2Async() { await Task.Delay(1); } //Task.Delay асинхронный, так его можно использовать для AMI. Прям тут и используют.
async Task Delay3Async() { await Task.Delay(1); } //Task.Delay асинхронный, так его можно использовать для AMI. Прям тут и используют.
async void DelayExternalAsync() { DelayAsync(); Delay2Async(); } //DelayAsync и Delay2Async асинхронные, так их можно использовать для AMI. Прям тут и используют.
async void DelayExternalAwaitAsync() { await Delay3Async(); } //Delay3Async асинхронный, так его можно использовать для AMI. Прям тут и используют.
//DelayExternalAsync и DelayExternalAwaitAsync асинхронные, так их можно использовать для AMI. Хотя тут их не используют для этого.
async Task<int> JustEmptyAsync() { return await Task.FromResult(1); } // JustEmptyAsync не асинхронный, так его не можно использовать для AMI в других местах, так как внутри ничего асинхронного.
- 它是一种发生非阻塞调用的方法。例子中,几乎所有方法都是异步的,但Task.Delay不是,因为它本身并没有AMI,至少看现有代码(也许不是这样,但我们暂时可以做这样的假设。虽然还有一个问题——有没有可以非阻塞调用的方法,但本身不包含AMI?如果有,那么这里我想用这个方法作为例子,否则这个选项好像是相当于第二个):
async void DelayAsync() { Task.Delay(1); } //DelayAsync асинхронный, так как в нем есть AMI
async void Delay2Async() { await Task.Delay(1); } //Delay2Async асинхронный, так как в нем есть AMI
async Task Delay3Async() { await Task.Delay(1); } //Delay3Async асинхронный, так как в нем есть AMI
async void DelayExternalAsync() { DelayAsync(); } //DelayExternalAsync асинхронный, так как в нем есть AMI
async void DelayExternalAwaitAsync() { await Delay3Async(); } //DelayExternalAwaitAsync асинхронный, так как в нем есть AMI
- 其他选项...
我们强调最初的问题,并用我们在研究资料时学到的东西来补充它
这个概念的起源是什么?它现在有什么意义?还是像许多其他众所周知但没有明确定义的术语一样 - 谁知道他想怎么做?随着时间的推移,是否有多个定义?
混在一堆人,马。
async仅表示该方法可以使用await. 就是这样,不代表别的。这些电话是否会出现 - 正如你所写的那样。如果那里没有调用await,那么该方法显然不是异步的。await是关于尝试异步执行任务。有些任务可以异步执行,有些则不能。因为Task本质上是某种工作的抽象,既然是抽象,那么不同的任务就会有不同的行为。例如,如果任务已经完成,那么尝试异步执行它已经太迟了。在上面的例子中,我们试图异步执行任务,但是那里没有什么可以执行的,因为任务已经被创建了。因为上面的代码又是同步代码。
是异步调用吗?好吧,从编程语言的角度来看,理论上是的。但是,它是异步执行吗?我们来看看定义
在上面的代码中,操作会在侧面进行吗?不,因为在上面的代码中,只有一个线程会异步等待另一个线程被阻塞。也就是说,上面的例子只是某种带有异步等待的多线程代码,也就是代码看似使用了异步机制,但并不是“异步执行”。
好吧,上面的代码从文件中读取文本。也就是说,它是一个 I/O 操作。此操作应由硬盘驱动器执行,而不是处理器。也就是说,在读取数据时,处理器什么也不做,没有线程被阻塞,硬盘驱动器正常工作,处理器继续它的业务,直到硬盘驱动器计算所有内容。即对硬盘设备进行读操作,CPU不锁定。这称为异步执行。
另一个例子是可能的。在这里,考虑类
这是一个普通窗口,并且能够异步等待用户关闭此窗口的那一刻。调用示例
这里发生了什么?我们在代码中异步等待用户。也就是说,根本不存在计算问题。操作在用户一方——当他完成窗口的工作时,他将关闭它——只有这样呼叫
await wnd.ShowAsync();才会结束。在这种情况下,没有线程被阻塞,没有任何计算。异步执行?相当,因为操作是由用户执行的,而不是设备。正如您在上面看到的,我们正在通过网络发出请求,并在完成后做出响应。也就是说,这样的逻辑是基于事件的,也不会阻塞任何东西。它被称为
Event-based Asynchronous Pattern (EAP)并被认为已过时,仅仅是因为它使您的代码看起来像事件面条。示例中是异步执行吗?是的。方法是异步的,它调用什么?不,普通方法,没有异步/等待。事实上,EAP并不方便,所以TAP (
Task-based asynchronous pattern) 来代替它。TAP 只是关于 async/await,但实际上它与 EAP 差不多,只是对程序员更友好。要理解这一点,您可以阅读有关如何将EAP 转换为 TAP的各种文章,或者这里有一个为您提供的实时示例。事件的存在是否保证某种异步执行?当然不是。是否可以将 EAP 用于异步调用 - 如果您不喜欢自己并且想要受苦,那么您可以。是否可以使用 EAP/TAP 进行异步调用?能。这能保证异步执行吗?当然不是。
在您帖子的原始版本中,在编辑之前,有这样的问题:
就在这里。异步编程模式。
async在带有关键字and的 TAP 出现之前await,有没有这样的词的 EAP 和 APM 异步编程模型。信息技术出现的时间比较晚,而且发展迅速。如果在人类活动的其他领域,术语和概念已经培育了几个世纪,那么在 IT 领域,它们必须在旅途中发明,并且经常从其他科学和专业借来。例如,很多东西都是从建筑行业借来的:“建筑”、“建造”(建造、建造)等术语。
异步的概念也存在于其他领域。
例如,力学中不等角速度的异步铰链。多亏了它们,轴可以以不同的速度旋转。
电气工程中的异步电动机。其中转子的旋转频率不等于磁场的旋转频率。
.NET 6 中的文件 IO 改进- 我阅读并抓住了我的头......异步实现中的许多错误。在外部,API 似乎是异步的,但在内部要么创建了额外的线程,要么使用了锁……
有些东西已经被修复了,但还有一些东西需要修复。而且有些问题一般不知道怎么解决,因为跨平台(该死)!在 Windows、Linux 和 Makosi 中,系统 API 的实现方式不同,因此很难将它们带入通用接口。
同样,我看到许多数据库提供程序仍然是同步的,即使它们的 .NET 实现提供了 Microsoft 推荐的异步方法。此外,这不是 DBMS 服务器的问题,而是将访问它们的客户端的问题。
在您提供的各种方法
DelayAsync中,没有一种:在这里,内部方法没有被驱逐,而是立即返回。这是可能的,因为它
Task是一个可等待的对象。因此,不需要修饰符
async。