• 彻底搞懂C#异步编程 async和await的原理


    1.前提

    熟练掌握Task并行编程。

    2.用Task并行解释async和await异步

    因为控制台有多线程操作的优化,因此这里选择winform来做示例。

    测试代码如下所示:
    有三个textbox,一个button

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace TestAsyncAwait
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Button1_Click(object sender, EventArgs e)
            {
                TestAsync();
    
                textBox3.Text = "333";
            }
    
    
            private async void TestAsync()
            {
                //Thread.Sleep(5000);//依然阻塞
    
                await Task.Run(() =>
                {
                    Thread.Sleep(2000);
    
                    this.Invoke((EventHandler)delegate { textBox1.Text = "1"; });
    
                    Thread.Sleep(2000);
    
                });
    
    
                this.Invoke((EventHandler)delegate { textBox2.Text = "22"; });
            }
    
        }
    }
    

    显示的顺序是:333,1,22

    如果在设置textbox显示内容之前,通过Thread.CurrentThread.ManagedThreadId属性来获取当前线程ID。

    可以得到textbox3所在为主线程,await之前也在主线程,await中和await后为新线程,这也是为什么在textbox1和textbox2的text加上invoke的原因。

    简单来时,实际上async和await就是表示,遇到await之后,函数直接返回,然后剩下的部分等同于在一个新线程中运行。

    使用Task并行编程的解释代码如下,将button按钮的click事件与TestAsync函数统一成TestTask函数

            private void TestTask()
            {
                Task.Run(() => 
                {
                    Task task = Task.Run(() =>
                    {
                        Thread.Sleep(2000);
    
                        this.Invoke((EventHandler)delegate { textBox1.Text = "1"; });
    
                        Thread.Sleep(2000);
                    });
    
                    Task.WaitAll(task);
    
                    this.Invoke((EventHandler)delegate { textBox2.Text = "22"; });
                });
    
                textBox3.Text = "333";
            }
    
    

    当然,上述代码也不完全等价async和await,只不过在实现功能上来说,没有差别。

    具体的差别表现为,waitall之前的线程与waitall之后所在线程不在同一个线程。这个差别也揭示了async和await的另外一个优势,那就是节约线程,内部实现了线程池优化。

    3.总结
    如果你懂得Task并行编程或者Thread多线程编程,其实async和await的原理是不难的,没有什么神乎其神的操作。

    async和await作为C#异步编程的语法糖,具有无可匹敌的优势,但是很多时候很多人不能理解用法,相比较而言直接使用Task并行编程会更加易懂。

    我的建议是,如果是新项目可以使用async和await,让自己的代码更简洁;如果是老项目维护,建议还是使用Task的方式维护,容易读懂。

  • 相关阅读:
    jQuery插件之artDialog
    jQuery插件之ajaxFileUpload
    jQuery插件之Cookie
    jQuery插件之Form
    jQuery与DOM对象的转换
    jQuery之AJAX
    jQuery之元素筛选
    jQuery之位置
    POJ2096 概率dp 入门
    Sichuan State Programming Contest 2012 C。Counting Pair
  • 原文地址:https://www.cnblogs.com/ligiggy/p/13630724.html
Copyright © 2020-2023  润新知