C# 5.0 中的 Async 和 Await
【博主】反骨仔 【本文】http://www.cnblogs.com/liqingwen/p/6069062.html
伴隨着 .NET 4.5 和 Visual Studio 2012 的 C# 5.0 ,我們可以使用的新的異步模式,這里涉及到 async 和 await 關鍵字。有許多不同點的觀點,比起之前我們所看到的代碼,它的可讀性和實用性是否更加突出。我們將通過一個例子,看看它與當前的做法有何“與眾不同”。
線性代碼與非線性代碼
大部分的軟件工程師習慣於用線性的思維方式去編程,也許是從他們開始職業生涯的時候就被這樣教導。當選擇使用線性思維的方式去編寫一個程序的時候,這意味着它的源碼在閱讀的時候有點像圖 1 。這假定我們有一個訂單系統將幫助我們從某處獲取一批訂單。
就算文章從左或從右開始,我們還是習慣於從上往下閱讀。如果有某些東西影響到了這塊內容的順序,我們將會感到很困惑,同時在這種問題的地方耗費更多的時間與精力,即便它沒有這個必要。基於事件的應用程序通常擁有這些非線性的結構。
基於事件的系統流程,它在觸發的同時,期待返回結果,圖2 很形象的表達了這點。初看這兩個序列似乎區別不大,但如果我們假設GetAllOrders返回 void ,這樣檢索訂單列表就不是那么直截了當了。
不看實際的代碼,我們認為線性方法處理起來更舒適,也不容易出錯。在這種情況下,錯誤可能不是運行時的錯誤或者編譯時的錯誤,而是在使用的時候出錯:由於缺乏清醒的認識。
基於事件的方法還有一個很大的優勢,它讓我們與使用基於事件的異步模式更相符。
在你看到一個方法的時候,你會有種想弄明白該方法的沖動。這意味着如果有一個叫 ReloadOrdersAndRefreshUI 的方法,你會去想弄明白加載訂單的情況,怎樣把它加入到UI,和當方法結束的時候會發生什么事情。在基於事件的方法里,這實現起來比較難。
另外一個好處是,只要在我們觸發 LoadOrdersCompleted 事件時,我們就能夠在 GetAllOrders 里編寫異步代碼,並返回到調用線程中去。
介紹一種新的模式
假設,我們在自己的系統上工作,系統使用上面提到過的 OrderHandler ,以及在實際中執行的是使用一個線性方法。為了模擬真實訂單系統的一小部分,OrderHandler 和 Order 如下:
1 class Order 2 { 3 public string OrderNumber { get; set; } 4 public decimal OrderTotal { get; set; } 5 public string Reference { get; set; } 6 } 7 class OrderHandler 8 { 9 private readonly IEnumerable<Order> _orders; 10 public OrderHandler() 11 { 12 _orders = new[] 13 { 14 new Order {OrderNumber = "F1", OrderTotal = 100, Reference = "Filip"}, 15 new Order {OrderNumber = "F1", OrderTotal = 100, Reference = "Filip"} 16 }; 17 } 18 public IEnumerable<Order> GetAllOrders() 19 { 20 return _orders; 21 } 22 }
因為我們在示例中不使用真實的數據源,我們可以為它增加點樂趣。這是關於異步編程的,我們想要在一個異步方式中請求一些東西。為了對此模擬,我們簡單的加入:
1 System.Threading.ManualResetEvent(false).WaitOne(2000) in GetAllOrders: 2 public IEnumerable<Order> GetAllOrders() 3 { 4 System.Threading.ManualResetEvent(false).WaitOne(2000); 5 return _orders; 6 }
--整理中--
【原文】http://www.dotnetcurry.com/csharp/869/async-await-csharp-dotnet
