RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1416834
Accepted
John
John
Asked:2022-08-04 06:31:37 +0000 UTC2022-08-04 06:31:37 +0000 UTC 2022-08-04 06:31:37 +0000 UTC

什么是 C# 和一般编程中的异步函数/方法?

  • 772

究竟什么应该称为异步方法?应该使用什么标准来调用异步方法?其他术语似乎很清楚,但让我们重复一下,以便我们可以进一步使用它来尝试定义异步方法的概念。

回忆相关概念

有一个异步方法调用(AMI)的概念——

在等待被调用代码完成时调用站点未被阻塞。相反,当回复到达时,调用线程会收到通知。

此外,调用这个词可以更改为调用或执行。

有一个异步的概念,但在编程中它似乎几乎可以与 AMI ( 1 ) 互换使用——

执行一个操作而不等待这个处理完成,执行的结果可以稍后处理。

他们经常举一个例子,用一个烧开的水壶来解释它是什么。

让我们寻找一个异步方法的定义,暂时忘记我们是如何想象它的,以便客观。

  1. 来源一 - async 关键字的文档-

使用 async 修饰符指定方法、lambda 表达式或匿名方法是异步的。如果在方法或表达式上使用此修饰符,它被称为异步方法。

可以翻译为:如果在方法或表达式中使用此修饰符,则称为异步方法。很明显,并非每个使用异步的方法都必须包含 AMI 或与现实中的异步相关的东西。

  1. 另一方面,有这样一个来源2:

异步方法是我们调用以启动冗长操作的方法。该方法应该执行启动操作所需的操作并“非常快速地”返回,以便没有处理延迟。

如果您的线程告诉该方法它需要完成工作,并且该方法说“好的,我会这样做,完成后我会打电话给您”,则该方法是异步的

这向我们暗示,在异步方法的定义中应该有一些关于 AMI 的内容,我们在上面回忆过。

  1. 甚至在旧 Dock 中的同一个 microsoftware 中(在 async 关键字出现之前),您也可以找到该术语的以下用法(3):

如果异步方法遇到未处理的异常,...

所以看起来这样的概念甚至在 async 关键字之前就已经存在,但也许随着它的出现,新的含义出现了纯粹与语言的语法有关。

  1. ...

不幸的是,研究这些来源需要很长时间,所以我有机会补充那些将回答这个问题的人。

试图从来源中找到定义。

根据所研究的来源,我想到了定义异步方法的哪些选项:

  1. 这是声明时带有 async 关键字的方法。例子:
async void SimpleAsync() {}
  1. 它是一种可用于非阻塞调用的方法。例子:
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 в других местах, так как внутри ничего асинхронного.
  1. 它是一种发生非阻塞调用的方法。例子中,几乎所有方法都是异步的,但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 
  1. 其他选项...

我们强调最初的问题,并用我们在研究资料时学到的东西来补充它

这个概念的起源是什么?它现在有什么意义?还是像许多其他众所周知但没有明确定义的术语一样 - 谁知道他想怎么做?随着时间的推移,是否有多个定义?

c# async-await
  • 2 2 个回答
  • 227 Views

2 个回答

  • Voted
  1. Best Answer
    tym32167
    2022-08-04T07:49:16Z2022-08-04T07:49:16Z

    混在一堆人,马。

    1. 该关键字async仅表示该方法可以使用await. 就是这样,不代表别的。这些电话是否会出现 - 正如你所写的那样。如果那里没有调用await,那么该方法显然不是异步的。
    async void SimpleAsync() {} // пустой метод - обычный синхронный пустой метод
    
    1. 关键字await是关于尝试异步执行任务。有些任务可以异步执行,有些则不能。因为Task本质上是某种工作的抽象,既然是抽象,那么不同的任务就会有不同的行为。例如,如果任务已经完成,那么尝试异步执行它已经太迟了。
    async void SimpleAsync2() {await Task.FromResult(0);}
    

    在上面的例子中,我们试图异步执行任务,但是那里没有什么可以执行的,因为任务已经被创建了。因为上面的代码又是同步代码。

    1. 好吧,现在让我们试着理解什么是“异步调用”。理论上,如果你调用一些代码,但不阻塞你自己的线程,那么调用将是异步的。
    async void SimpleAsync3() {await Task.Run(()=>Thread.Sleep(1000));}
    

    是异步调用吗?好吧,从编程语言的角度来看,理论上是的。但是,它是异步执行吗?我们来看看定义

    异步执行

    异步意味着操作可以由旁边的某个人执行:远程 Web 主机、服务器或当前计算设备之外的其他设备。

    这种操作的主要特性是,这种操作的开始所需的时间比主要工作要少得多。这使您即使在具有少量计算设备的设备上也可以同时执行许多异步操作。

    在上面的代码中,操作会在侧面进行吗?不,因为在上面的代码中,只有一个线程会异步等待另一个线程被阻塞。也就是说,上面的例子只是某种带有异步等待的多线程代码,也就是代码看似使用了异步机制,但并不是“异步执行”。

    1. 那么,让我们看看一些代码,它不仅看起来像异步,而且像异步一样工作。
    async void SimpleAsync4() {await File.ReadAllTextAsync("..."); }
    

    好吧,上面的代码从文件中读取文本。也就是说,它是一个 I/O 操作。此操作应由硬盘驱动器执行,而不是处理器。也就是说,在读取数据时,处理器什么也不做,没有线程被阻塞,硬盘驱动器正常工作,处理器继续它的业务,直到硬盘驱动器计算所有内容。即对硬盘设备进行读操作,CPU不锁定。这称为异步执行。

    另一个例子是可能的。在这里,考虑类

    public class Wnd : Window
    {
        TaskCompletionSource<object> s;
    
        public Wnd()
        {
            s = new TaskCompletionSource<object>();     
            this.Closed+= (sender, args) => s.SetResult(this);
        }
    
        public Task ShowAsync()
        {
            this.Show();
            return s.Task;
        }
    }   
    

    这是一个普通窗口,并且能够异步等待用户关闭此窗口的那一刻。调用示例

    async Task AsyncBased()
    {
        var i = DoSmthg();
        var wnd = new Wnd();
        await wnd.ShowAsync();
        DoSmthgElse(i);
    }
    

    这里发生了什么?我们在代码中异步等待用户。也就是说,根本不存在计算问题。操作在用户一方——当他完成窗口的工作时,他将关闭它——只有这样呼叫await wnd.ShowAsync();才会结束。在这种情况下,没有线程被阻塞,没有任何计算。异步执行?相当,因为操作是由用户执行的,而不是设备。

    1. 那么,现在的问题。好的,我们理解有“异步调用”,但不代表“异步执行”。也就是说,您可以异步调用某些内容,但执行将是同步的。或异步。你怎么写。没有异步调用可以异步执行吗?(不带异步/等待读取)?其实,是。没有什么能阻止您在另一台设备上开始操作,当它结束时,做点什么。好吧,举个例子
        var wc = new WebClient();
        wc.DownloadStringCompleted += (sender, args) => {Console.WriteLine("Completed");}
        wc.DownloadStringAsync(new Uri("...."));
    

    正如您在上面看到的,我们正在通过网络发出请求,并在完成后做出响应。也就是说,这样的逻辑是基于事件的,也不会阻塞任何东西。它被称为Event-based Asynchronous Pattern (EAP)并被认为已过时,仅仅是因为它使您的代码看起来像事件面条。示例中是异步执行吗?是的。方法是异步的,它调用什么?不,普通方法,没有异步/等待。

    事实上,EAP并不方便,所以TAP ( Task-based asynchronous pattern ) 来代替它。TAP 只是关于 async/await,但实际上它与 EAP 差不多,只是对程序员更友好。要理解这一点,您可以阅读有关如何将EAP 转换为 TAP的各种文章,或者这里有一个为您提供的实时示例。事件的存在是否保证某种异步执行?当然不是。是否可以将 EAP 用于异步调用 - 如果您不喜欢自己并且想要受苦,那么您可以。

    是否可以使用 EAP/TAP 进行异步调用?能。这能保证异步执行吗?当然不是。

    • 3
  2. Alexander Petrov
    2022-08-05T22:03:43Z2022-08-05T22:03:43Z

    在您帖子的原始版本中,在编辑之前,有这样的问题:

    所以似乎有一个与关键字无关的概念?

    就在这里。异步编程模式。async在带有关键字and的 TAP 出现之前await,有没有这样的词的 EAP 和 APM 异步编程模型。

    这个概念的起源是什么?它现在有什么意义?还是像许多其他众所周知但没有明确定义的术语一样 - 谁知道他想怎么做?

    信息技术出现的时间比较晚,而且发展迅速。如果在人类活动的其他领域,术语和概念已经培育了几个世纪,那么在 IT 领域,它们必须在旅途中发明,并且经常从其他科学和专业借来。例如,很多东西都是从建筑行业借来的:“建筑”、“建造”(建造、建造)等术语。

    异步的概念也存在于其他领域。
    例如,力学中不等角速度的异步铰链。多亏了它们,轴可以以不同的速度旋转。
    电气工程中的异步电动机。其中转子的旋转频率不等于磁场的旋转频率。

    是否有可以称为非阻塞但本身不包含 AMI 的方法?

    .NET 6 中的文件 IO 改进- 我阅读并抓住了我的头......异步实现中的许多错误。在外部,API 似乎是异步的,但在内部要么创建了额外的线程,要么使用了锁……
    有些东西已经被修复了,但还有一些东西需要修复。而且有些问题一般不知道怎么解决,因为跨平台(该死)!在 Windows、Linux 和 Makosi 中,系统 API 的实现方式不同,因此很难将它们带入通用接口。

    同样,我看到许多数据库提供程序仍然是同步的,即使它们的 .NET 实现提供了 Microsoft 推荐的异步方法。此外,这不是 DBMS 服务器的问题,而是将访问它们的客户端的问题。


    在您提供的各种方法DelayAsync中,没有一种:

    Task DelayAsync() { return Task.Delay(1); }
    

    在这里,内部方法没有被驱逐,而是立即返回。这是可能的,因为它Task是一个可等待的对象。
    因此,不需要修饰符async。

    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5