關於async、await、Task和Task 的小例子


沒什么好說的,代碼注釋寫的很詳細,4個簡單例子,沒有高深語法,復制到編輯器運行看看注釋應該就能理解了,我也是萌新,對這2個概念一直比較迷惑,分享出來共同進步。

using System;
using System.Threading.Tasks;

namespace TestAsync
{
    class TestAsync
    {
        static void Main()
        {
            DoSomething1(); //沒有 Wait,如果沒有 Read()等待,而 DoSomething1 延遲 5 秒輸出,DoSomething3 只會延遲 1 秒,主程序會在 DoSomething1 之前結束,導致沒有輸出
            DoSomething2();
            DoSomething3().Wait(); //有 Wait,等 DoSomething3 執行完再繼續執行,否則在沒有 Read()等待的情況下,會出現 DoSomething3 沒有執行完,主程序就結束了

            int i = 10;
            DoSomething4<int>(i);

            Console.WriteLine("DoSomething3全部執行,DoSomething4第一段輸出之后");  //因為有Wait(),會在執行完DoSomething2之后執行
            Console.Read();         //用等待輸入讓主程序不結束,這樣不用Wait也可以
        }

        //單獨使用async,async聲明表示這是一個異步方法,可以搭配await語句異步處理
        //在async聲明的方法中可以使用await回調,注意async可以沒有await,但是await不能沒有async,有async沒有await就沒有異步功能,還是一個同步方法
        //await的本質是一個隱式回調,意思是創建一個等待返回的Task,返回之后繼續后面的代碼,所以如果有await語句可以不用顯式reture
        //await必須搭配一個Task語句使用,否則報錯:未找到GetAwaiter的定義
        public static async void DoSomething1()
        {
            int i = 10;
            await Task.Delay(5000); //阻塞后面語句等待延遲結束
            Console.WriteLine("DoSomething1:Task.Delay:" + 5000);
            i += 10;
            Console.WriteLine("DoSomething1:i:" + i);
        }

        //單獨使用Task,Task聲明的方法必須有類型是Task的返回值,否則報錯
        //Task僅表示不用等待,可以繼續執行后續代碼,但並不是異步功能,因此主程序的調用不會等DoSomething2執行完才繼續
        public static Task DoSomething2()
        {
            int i = 10;
            Task.Delay(50000);  //Delay多少都沒卵用
            Console.WriteLine("DoSomething2:Task.Delay:" + 50000);
            i += 10;
            return Task.Run(() => Console.WriteLine("DoSomething2:i:" + i));
        }

        //Task、async、await三位一體才能算是異步方法,缺少任何其中一個,要么報錯無法編譯,要么還是同步方法,實現不了異步功能
        //Task.Delay()的作用是啟動一個Task,Task開啟定時器,延時指定時間
        //但是不和await一起使用,則僅僅是創建了一個Task去執行定時器任務,不會阻塞后面的語句繼續執行,和DoSomething2同理
        //因此第一段輸出會立即執行,不是1秒后輸出
        //await會阻塞后面的語句等待返回才會繼續執行,因此第二段輸出在1秒后輸出
        public static async Task DoSomething3()
        {
            int i = 10;
            Task.Delay(1000);   //Delay多少都沒卵用
            Console.WriteLine("DoSomething3:Task.Delay:" + 1000);
            i += 10;

            await Task.Delay(1000); //阻塞后面語句等待延遲結束
            Console.WriteLine("DoSomething3:Task.Delay:" + 1000);
            Console.WriteLine("DoSomething3:i:" + i);
        }

        //那么Task<T>又怎么理解?
        //首先單獨的Task<T> fun()只是一個同步方法,返回值是Task<T>,而不是T,而async Task<T> fun(){ await xxx }才是異步方法,返回的是T,不是Task<T>
        //那么async Task沒有<T>,當然就是一個沒有返回值的異步方法了
        public static async Task<T> DoSomething4<T>(T t)
        {
            int i = 10;
            Task.Delay(1000);
            Console.WriteLine("DoSomething4:Task.Delay:" + 1000);
            i += 10;

            await Task.Delay(1000);
            Console.WriteLine("DoSomething4:Task.Delay:" + 1000);
            Console.WriteLine("DoSomething4:i:" + i);

            Console.WriteLine("DoSomething4:T:" + typeof(T));
            return t;
        }
    }

}

//輸出結果
//DoSomething3:Task.Delay:1000
//DoSomething2:Task.Delay:50000
//DoSomething2:i:20
//DoSomething3:Task.Delay:1000
//DoSomething3:i:20
//DoSomething4:Task.Delay:1000
//DoSomething3 全部執行,DoSomething4 第一段輸出之后
//DoSomething4:Task.Delay:1000
//DoSomething4:i:20
//DoSomething4:T:System.Int32
//DoSomething1:Task.Delay:5000
//DoSomething1:i:20

//輸出結果理解
//DoSomething1 異步延遲 5 秒輸出,肯定在最后
//DoSomething2 的 Delay 沒卵用,DoSomething3 的第一個 Delay 同理,都是立即執行而且沒有 Wait,因此誰先誰后不一定
//DoSomething3 有 Wait(),必然是先於 DoSomething4 執行,即使 DoSomething4 第一段輸出是立即執行也沒用
//但是 DoSomething4 的第一段輸出在主程序輸出之前,所以主程序輸出在 DoSomething4 第一段輸出之后
//然后是 DoSomething4 的第二段輸出和 T 類型輸出,此時時間只過了 2 秒,而 DoSomething1 延遲 5 秒輸出還沒到
//到第 5 秒,輸出 DoSomething1 的信息


免責聲明!

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



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