Async Await異步調用WebApi


先鋪墊一些基礎知識

在 .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
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM