前面一篇文章,了解了任務並行庫。這是異步編程基礎設施,它允許我們以模塊化的方式設計程序,來組合不同的異步操作。解決了以往線程之間傳遞消息難等問題,但是我們在閱讀和編寫此類程序時還是會覺得非常難理解程序的實際執行順利,總感覺把主動權交給並行庫,總覺得心里面沒底。而且隨着系統的不斷擴大,業務的不斷完善,了解程序的先后執行次序就變得很重要。
C#5.0
在C#5.0中,微軟引入了一個全新的語言特性,異步函數。它是TPL之上的更高級別的抽象,真正簡化了異步編程。
抽象隱藏了主要的實現細節,使得程序員無需考慮許多重要的事情,從而使異步編程更加容易。
async Task<string> GetStringAsync()
{
await Task.Delay(TimeSpan.FromSeconds(2));
return "你好,阿輝";
}
一、async和await
- 在async標識的方法體里面,如果沒有await關鍵字出現,那么這種方法和調用普通的方法沒什么區別。
- 在async標識的方法體里面,在await關鍵字出現之前,還是主線程順序調用執行,知道await關鍵字的出現才會出現線程阻塞。
- await關鍵字可以理解為等待方法執行完畢,除了可以標記有async關鍵字的方法外還能標記Task對象,標識等待該線程執行完畢。所以await關鍵字並不針對於asyncd的方法,而是針對async方法所返回給我們的Task。
- async方法的返回類型必須為void、Task或者Task
類型,說白了,async要么是void,要么和Task關聯。
在async方法外不能使用await關鍵字,否則編譯錯誤。異步函數在代碼中至少要擁有一個await操作符,如果沒有,也不會報錯,只是會提示警告。
在ASP.NET程序中,一旦在代碼中使用了異步,最好一直使用。調用異步方法時,應該用await等待它返回Task對象,一定要避免使用Task.Wait或Task
public ActionResult DeadLock()
{
Task task = WaitAsync();
//同步程序塊,正在等待異步方法完成
task.Wait();
return Content("執行完畢");
}
async Task WaitAsync()
{
await Task.Delay(TimeSpan.FromSeconds(5));
}
在DeadLock()方法中,當執行到task.Wait()方法時,主線程會被阻塞,不往下執行。等候WaitAsync()異步方法執行完畢后,才解除阻塞。
在C#5.0中,await和Async是有一定的限制的。
- 不能把控制台中的Main()方法標記為async.
- 不能在catch、finally、lock或unsafe代碼塊中使用await操作符。
- 不允許對任何異步函數使用ref或out參數。
並不是所有的方法都得上Async的,對於需要異步處理的該使用async/await就使用,不需要的就使用平常方法。平常的方法在性能方面要比async關鍵字方法塊40~50倍。所以我們在平時也要注意不能濫用async。
二、使用await操作符獲取異步任務結果
async static Task WithWait()
{
try
{
string result = await GetInfoAsync("阿輝");
Console.WriteLine(result);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
async static Task<string> GetInfoAsync(string name)
{
await Task.Delay(TimeSpan.FromSeconds(2));
return name+",你好。";
}
Task t = WithWait();
t.Wait();
這樣就可以獲取到異步任務的返回值了。使用await后,C#立即創建了一個任務,其有一個后續操作任務,包含了await操作符后面的所有剩余代碼。這個新任務也處理了異常傳播。然后將任務返回到主方法中並等待其完成。
目前在最新的.NET Core中,基本上所有方法都默認在使用await/async這種模式來編寫。所以學習這種異步編程方式還是特別有意義的。
好了,今天的學習就到這里,我們下篇文章見。
小寄語
人生短暫,我不想去追求自己看不見的,我只想抓住我能看的見的。
原創不易,給個關注。
我是阿輝,感謝您的閱讀,如果對你有幫助,麻煩點贊、轉發 謝謝。
