zoukankan      html  css  js  c++  java
  • 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
     
  • 相关阅读:
    MapReduce in MongoDB
    MongoDB的一些基本操作
    谈谈NOSQL
    Java中的反射(1)
    Mybatisの常见面试题
    关于Lombok和自动生成get set方法
    订Pizza(Java)
    美化Div的边框
    爱,死亡和机器人(Love,Death&Robots)
    session与cookie的介绍和两者的区别之其相互的关系
  • 原文地址:https://www.cnblogs.com/JasonShenW/p/5193785.html
Copyright © 2011-2022 走看看