浅谈Async和Await如何简化异步编程(几个实例让你彻底明白)

2019-12-30 15:22:57于海丽

传统的异步编程来改善程序的响应

上面部分我们已经看到同步方法所带来的实际问题了,为了解决类似的问题,.NET Framework很早就提供了对异步编程的支持,下面就用.NET 1.0中提出的异步编程模型(APM)来解决上面的问题,具体代码如下(注释的部分通过获得GUI线程的同步上文对象,然后同步调用同步上下文对象的post方法把要调用的方法交给GUI线程去处理,因为控件本来就是由GUI线程创建的,然后由它自己执行访问控件的操作就不存在跨线程的问题了,程序中使用的是调用RichTextBox控件的Invoke方式来异步回调访问控件的方法,其实背后的原来和注释部分是一样的,调用RichTextBox控件的Invoke方法可以获得创建RichTextBox控件的线程信息(也就是前一种方式的同步上下文),然后让Invoke回调的方法在该线程上运行):


private void btnClick_Click(object sender, EventArgs e)
    {
      this.richTextBox1.Clear();
      btnClick.Enabled = false;
      AsyncMethodCaller caller = new AsyncMethodCaller(TestMethod);
      IAsyncResult result = caller.BeginInvoke(GetResult, null);

      //// 捕捉调用线程的同步上下文派生对象
      //sc= SynchronizationContext.Current;
    }

    # region 使用APM实现异步编程
    // 同步方法
    private string TestMethod()
    {    
      // 模拟做一些耗时的操作
      // 实际项目中可能是读取一个大文件或者从远程服务器中获取数据等。
      for (int i = 0; i < 10; i++)
      {
        Thread.Sleep(200);
      }

      return "点击我按钮事件完成";
    }

    // 回调方法
    private void GetResult(IAsyncResult result)
    {
      AsyncMethodCaller caller = (AsyncMethodCaller)((AsyncResult)result).AsyncDelegate;
      // 调用EndInvoke去等待异步调用完成并且获得返回值
      // 如果异步调用尚未完成,则 EndInvoke 会一直阻止调用线程,直到异步调用完成
      string resultvalue = caller.EndInvoke(result);
      //sc.Post(ShowState,resultvalue);
      richTextBox1.Invoke(showStateCallback, resultvalue);
    }

    // 显示结果到richTextBox
    private void ShowState(object result)
    {
      richTextBox1.Text = result.ToString();
      btnClick.Enabled = true;
    }

    // 显示结果到richTextBox
    //private void ShowState(string result)
    //{
    //  richTextBox1.Text = result;
    //  btnClick.Enabled = true;
    //}
    #endregion

运行的结果为:

async,await,c#,async异步编程,异步

C# 5.0 提供的async和await使异步编程更简单

上面部分演示了使用传统的异步编程模型(APM)来解决同步代码所存在的问题,然而在.NET 2.0,.NET 4.0和.NET 4.5中,微软都有推出新的方式来解决同步代码的问题,他们分别为基于事件的异步模式,基于任务的异步模式和提供async和await关键字来对异步编程支持。关于前两种异步编程模式,在我前面的文章中都有介绍,大家可以查看相关文章进行详细地了解,本部分就C# 5.0中的async和await这两个关键字如何实现异步编程的问题来给大家介绍下。下面通过代码来了解下如何使用async和await关键字来实现异步编程,并且大家也可以参看前面的博客来对比理解使用async和await是异步编程更简单。