zoukankan      html  css  js  c++  java
  • 15.1 异步函数简介与思考

     1     public partial class AsyncForm : Form
     2     {
     3         Label label;
     4         Button button;
     5         public AsyncForm()
     6         {
     7             InitializeComponent();
     8             label = new Label { Location = new Point(this.Size.Width / 2, 20), Text = "Length" };
     9             button = new Button { Location = new Point(this.Size.Width / 2, 50), Text = "Click" };
    10             button.Click += DisPlayWebSiteLength;
    11             AutoSize = true;
    12             Controls.Add(label);
    13             Controls.Add(button);
    14         }
    15         async void DisPlayWebSiteLength(object sender, EventArgs e)
    16         {
    17             label.Text = "Fetching";
    18             using (HttpClient client = new HttpClient())
    19             {
    20                 Task<string> task = client.GetStringAsync("https://www.baidu.com/");
    21                 string text = await task;
    22                 label.Text = text.Length.ToString();
    23             }
    24         }
    25     }

    注意, task 的类型是 Task<string> ,而 await task 表达式的类型是 string 。也就是说,
    await 表达式执行的是“拆包”(unwrap)操作,至少在被等待的值为 Task<TResult> 时是这样。
    (还可以等待其他类型,但 Task<TResult> 是一个不错的起点。)这是 await 的一个方面,看上
    去跟异步编程没什么直接关系,但却让生活更加轻松。
    await 的主要目的是在等待耗时操作完成时避免阻塞。它是如何在具体线程中工作的呢?我
    们在方法的开始和结束处都设置了 label.Text ,所以可以很自然地认为这两条语句都在UI线程
    执行。但显然我们在等待页面下载的时候没有阻塞UI线程。

    后续操作 后续操作指在异步操作(或任何 Task )完成时执行的回调程序。在异步方法
    中,后续操作保留了方法的控制状态。就像闭包保留了环境中的变量一样,后续操作记
    住了它的位置,因此在执行时可回到原处。 Task 类包含一个专门用于添加后续操作的方
    法,即 Task.ContinueWith 。

    如果在 await 表达式后的代码中加入断点(假设 await 表达式需要后续操作),你会发现堆
    栈跟踪中不再拥有 Button.OnClick 方法,该方法早已执行完毕。现在的调用栈是纯粹的
    Windows Forms事件循环,在顶部还有一些异步基本结构。如果为了适时地更新UI,而在后台线
    程中调用 Control.Invoke ,将得到跟现在非常类似的调用栈,然而现在这些工作已经完全为我
    们做好了。起初发现调用栈在眼皮底下发生如此显著的变化时,你可能会有些沮丧,但这对异步
    编程来说是绝对必要的。

    15.2.2 异步方法

     1     class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             PrintPageLength();
     6 
     7             Console.ReadKey();
     8         }
     9 
    10         static void PrintPageLength()
    11         {
    12             Task<int> task = GetPageLengthAsync("https://www.baidu.com/");
    13             Console.WriteLine(task.Result);
    14         }
    15 
    16         async static Task<int> GetPageLengthAsync(string url)
    17         {
    18             using (HttpClient client = new HttpClient())
    19             {
    20                 Task<string> task = client.GetStringAsync(url);
    21                 int lenth = (await task).Length;
    22                 return lenth;
    23 
    24             }
    25         }
    26     }
  • 相关阅读:
    2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 C: Coconut
    2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 A: Banana
    第2周项目1c++语言中函数参数传递的三种方式
    第2周项目2程序的多文件组织
    【BZOJ 3224】普通平衡树
    【POJ 1741】Tree
    浅谈树分治
    【luogu 2709 / BZOJ 3781】小B的询问
    【luogu 1972 / BZOJ 1878】HH的项链
    【BZOJ 3339 / BZOJ 3585 / luogu 4137】Rmq Problem / mex
  • 原文地址:https://www.cnblogs.com/kikyoqiang/p/10122614.html
Copyright © 2011-2022 走看看