Async Await異步調用WebApi

先鋪墊一些基礎知識web

在 .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
相關文章
相關標籤/搜索