先鋪墊一些基礎知識 在 .net 4.5中出現了 Async Await關鍵字,配合之前版本的Task 來使得開發非同步程式更為簡單易控。 在使用它們之前 我們先關心下 為什麼要使用它們。好比 一個人做幾件事,那他得一件一件的做完,而如果添加幾個人手一起幫著做 很顯然任務會更快的做好。這就是並行的粗淺
先鋪墊一些基礎知識
在 .net 4.5中出現了 Async Await關鍵字,配合之前版本的Task 來使得開發非同步程式更為簡單易控。 在使用它們之前 我們先關心下 為什麼要使用它們。好比 一個人做幾件事,那他得一件一件的做完,而如果添加幾個人手一起幫著做 很顯然任務會更快的做好。這就是並行的粗淺含義。 在程式中,常見的性能瓶頸在於 NetWork I/O 瓶頸 , CPU 瓶頸, 資料庫I/O瓶頸,這些瓶頸使得我們的程式運行的很慢,我們想辦法去優化。因為並行開發本身就加重CPU負擔,所以一般將並行用來優化 由另外兩種I/O造成的瓶頸。//sync method sample public static void DownLoadWebPage() { //TODO cost 5s Console.WriteLine( "DownLoadWebPage on Thread:{0}", Thread.CurrentThread.ManagedThreadId); Thread.Sleep(5000); Console.WriteLine( "End downloading the page.." ); } public static void LoadDatafromDB() { //TODO cost 5s Console.WriteLine( "LoadDataFromDB on Thread:{0}", Thread.CurrentThread.ManagedThreadId); Thread.Sleep(5000); Console.WriteLine( "End loading Data.." ); }比如這邊的兩個方法, 通過Thread.Sleep來模擬程式耗時5秒,那如果我們再寫一個方法來調用
public static void OurSyncJob() { Console.WriteLine( "start doing things sync" ); DownLoadWebPage(); LoadDatafromDB(); //do some other things Console.WriteLine( "do some other things" ); }很顯然 會耗時超過10s鐘,如果我們用task開啟兩個線程 同時執行 如下
public static async Task OurAsyncJobTask() { Console.WriteLine( "start doing things async" ); var taskA= Task.Run(() => { DownLoadWebPage(); }); var taskB= Task.Run(() => { LoadDatafromDB(); }); await Task.WhenAll(taskA,taskB); Console.WriteLine( "do some other things" ); }那執行時間只會是5s多一點, 大大提升了我們程式的性能。 在瞭解了這些基礎之後,我們來接觸非同步程式的實際運用場景。 我們調用 WebApi的時候,因為要經過網路傳輸,有時候會很慢。 這時候便有了我們用非同步一展身手的時候了。 我們的webapi如下
public class ProductController : ApiController { public productRepo repo = new productRepo(); public IEnumerable< Product> getProducts() { Thread.Sleep(5000); return repo.GetAll(); } } public class WidgetController : ApiController { public widgetRepo repo = new widgetRepo(); public IEnumerable< Widget> getWidgets() { Thread.Sleep(5000); return repo.GetAll(); } }都是模擬耗時5秒鐘,現在要同時調用這些api獲得 數據並一起展示
public static List <Product > TaskGetProduct() { using( HttpClient client= new HttpClient()) { client.BaseAddress = new Uri( "http://localhost:52593/" ); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue ("application/json" )); string json = client.GetString("api/Product/Products" ); return JsonConvert.DeserializeObject< List< Product>>(json); } }很顯然 調用這個webapi要5秒多,那麼我們要同時獲取的時候,就要分別調用TaskGetProduct() TaskGetWidget() TaskGetGizmos() 和前面的經驗一樣,這要是同步的話不得15秒多。。這要如何忍受。。 很顯然要非同步獲取
public static async Task< List< Product>> TaskGetProduct() { using( HttpClient client= new HttpClient()) { client.BaseAddress = new Uri( "http://localhost:52593/" ); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue ("application/json" )); string json = await client.GetStringAsync("api/Product/Products" ); return JsonConvert.DeserializeObject< List< Product>>(json); } } public static async Task< pwgVM> RunTaskGetAll() { var task1 = TaskGetItem< Product>(); var task2 = TaskGetItem< Gizmos>(); var task3 = TaskGetItem< Widget>(); await Task.WhenAll(task1,task2,task3); pwgVM vm = new pwgVM(task1.Result,task2.Result,task3.Result); return vm; }三個任務同時進行,花費5秒多。ok 附上源代碼 http://files.cnblogs.com/files/JasonShenW/WebApi.rar http://files.cnblogs.com/files/JasonShenW/WebMVC.rar