沒什么好說的,代碼注釋寫的很詳細,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 的信息