单线程上的异步编程

时间:2018-05-01 07:08:22

标签: .net asynchronous async-await

我试图通过http://blog.stephencleary.com/2012/02/async-and-await.html理解异步编程的概念 和https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/文章,这些是我的发现:

  1. 用于执行非阻止呼叫
  2. 每当执行昂贵的请求并且花费更长的时间时,异步调用将返回调用者并执行其他操作,并且当异步请求完成时,它将返回数据。
  3. 这一切都在单线程中进行。
  4. 另外,我试图通过以下代码复制这个概念:

    private async void button1_Click(object sender, EventArgs e)
            {
                Task<int> contentLength = mainMethod();
                Console.WriteLine("button_click");
                int length = await contentLength;
                Console.WriteLine(length);
            }
    
            private async Task<int> mainMethod()
            {
                int contentLength = await AccessWebsiteAync();
                Console.WriteLine("main method");
                return contentLength;
            }
    
            async Task<int> AccessWebsiteAync()
            {
                HttpClient client = new HttpClient();
                Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
                string urlContents = await getStringTask;
                return urlContents.Length;
            }
    
    output : button_click
            main method
            40692
    

    根据我的理解和以上输出,这是我的疑惑:

    1. 这是client.GetStringAsync("http://msdn.microsoft.com");一个昂贵的电话,所以它会被返回给来电者 打印button_click。通话如何知道它是否昂贵?
    2. 它在哪里存储了一个详细呼叫的状态,以及它如何在以后检索昂贵的呼叫?
    3. 如何在后台执行昂贵的通话?
    4. 我知道我的理解非常混乱。任何消化?

2 个答案:

答案 0 :(得分:3)

我认为最好不要直接阅读async await,而是了解异步编程究竟是什么。在Python中,有一个good article.Net也可能有类似的。

网络呼叫是一种输入/输出操作,它不需要CPU但仍需要时间。如果您要等待它,则浪费您的程序时间(从操作系统调度程序获得的共享)。因此,只需让您的程序创建一个网络套接字,发送请求,在队列中监控并继续,您就会变得聪明且敏感。该程序将持续监视所有使用某些API(如select排队的套接字并处理相应的回调。

想想你是酒店的接待员。在同步方法中,接待员会接受命令并消失,直到他得到答复。在异步方法中,他只需要您的订单并维护日志。他会经常检查状态,并处理它们。

  

通话如何知道它是否昂贵?

如果你等待,任何输入/输出限制的东西在时间上都会很昂贵。智能操作系统在您准备好之前不会安排您的程序。因此,如果您要执行某些独立任务,则需要根据该程序编写程序。如果它受CPU限制,那么就不要以异步方式进行。

  

它在哪里存储昂贵电话的状态?

就您的程序而言,您将其抽象为套接字或文件描述符,并监视它是否已准备就绪。其余部分由操作系统和其他相关服务器完成。

  

如何在后台执行昂贵的通话?

操作系统完成TCP / IP处理工作,实际计算由网络中的其他服务器完成。

答案 1 :(得分:1)

  

通话如何知道它是否昂贵?

通话不需要&#34;知道&#34;任何东西。例如,您可以await Task.CompletedTask;,实际上是NOP。

  

它在哪里存储了一个密集呼叫的状态......

当方法标记为async时,编译器会生成一个辅助类。您当地的vars&#39;实现为对象字段等。

  

如何在后台执行昂贵的通话?

大多数I / O都是异步的。该任务在I/O CompletionPort上排队,并在数据进入时重新安排。

在我们使用async / await之前,我们必须使用回调方法,你的button1_Click()将被编写为2个单独的方法,一个设置I / O操作,另一个设置处理结果。