徹底搞懂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的方式維護,容易讀懂。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM