zoukankan      html  css  js  c++  java
  • Aspnet MVC 异步调用

    一个简图来描述下Aspnet MVC下的异步调用

      { request } 
      /    /
    -------ISS------- > work thread
      |      
      |         route - aysn controller
      |        
      |          [invoke] clr thread pool 
      |         /
      |        /
      |       /  complete -> asyncManager 
      |      /
      |------asyncManager 


    从简图可以了解:
    用户发送请求,服务器路由到控制器,控制器到action,action内部通过线程池调用新线程执行request,然后将数据返回给用户。


    该简图涉及到controller的一个属性AsyncManager
    asyncManagerde的作用主要体现在两点:
    1. 标识异步的开始和结束,通 过  AsyncManager.OutstandingOperations.Increment/OutstandingOperations.Decrement
    2. 在执行线程到结束回调过程中的参数传递 通过AsyncManager.Parameters (类型为字典,传递参数时候需要注意Key需要跟结果参数回调的参数名一致)。

    asyncManager在异步调用中并不是必须的。

    异步虽好,但并不是所有的场合都是适合的,一般来说如果没有长耗时和分布的需求情况下,异步是没要的

    在aspnet mvc中实现异步操作有三种方式:

    1.通过异步控制器AsyncController
      自定义控制器通过继承AsyncController,在内部定义XXXAsync/XXXCompleted格式的action,例如:

      

    public void IndexAsync() { }
    public ActionResult IndexCompleted(string parameter);
    
    //其中indexCompleted中的参数parameter
    //通过AsyncManager.Parameters ["parameter'] = XX传递
    //参数名和KEY要保持一致性

     Async和completed定义总是成对出现了,async定义的方法用于执行异步操作,而completed定义的方法用于返回结果.

     通过XXasync和XXcompeleted定义的方法,ASPNET MVC在调用时候并不是以异步的方式调用,所以真正的工作还是需要我们自己async中定义异步操作.一个简单的例子:

        public class CustomAsyncController: AsyncController
        {
            public void IndexAsync() {
                //increment不写参数情况默认计数为1
                //如果存在多个task需要添加相应的计数值,以保证结果能正确的返回
                AsyncManager.OutstandingOperations.Increment(); 
                Task.Factory.StartNew(() =>
               {
                   int sum = 0;
                   for (int i = 0; i < 10000000; i++) { sum += i; }
    
                   //传递参数给XXXCompleted
                   AsyncManager.Parameters["sum"] = sum;
    
                   //end
                   AsyncManager.OutstandingOperations.Decrement();//多个任务要多次调用,调用次数一般等于increment中设置的计数 
               });
                     
            }
            public ActionResult IndexCompleted(string sum)
            {
                return Content(sum.ToString());
            }
        }
    View Code

    2.通过async和await关键字

     async/await关键字用于标识异步操作,我们用一个简单的例子来演示async/await的使用

     a.例子我们先定义个webapi,用于返回用户信息

     b.通过服务类,异步调用改用webapi接口返回用户信息

     c.控制器调用服务类返回数据结果

        public class UserController : ApiController
        {
            private static UserRepository _respository = new UserRepository();
    
            [System.Web.Http.HttpGet]
            public IList<UserModel> GetAll()
            {
                return _respository.GetAll();
            }
        }
       public class UserService
        {
            private static UserService instance = null;
            public static UserService Instance
            {
                get
                {
                    if (instance == null)
                        instance = new UserService();
    
                    return instance;
                }
            }
            public async Task<IList<UserModel>> GetUsersAsync( CancellationToken token =default(CancellationToken))
            {
                var uri = "http://localhost:3541/api/user/getall";
                using(HttpClient client  = new HttpClient())
                {
                    var response = await client.GetAsync(uri);
                    return await response.Content.ReadAsAsync<IList<UserModel>>();
                }
            }
        }
        public class CustomController : Controller
        {
           public async Task<ActionResult> Index()
            {
                 IList < UserModel > models = await UserService.Instance.GetUsersAsync();
    
                return Json(models,JsonRequestBehavior.AllowGet);
            }
        }

    3.直接通过返回task实现异步

      最简单最直接的一种方式了

     

        public class HomeController : AsyncController
        {
            public Task<ActionResult> Index()
            {
                return Task.Factory.StartNew(() =>
               {
                   return new List<UserModel>
                   {
                        new UserModel {Name ="visonme" },
                        new UserModel {Name = "visonme2" }
                   };
               }).ContinueWith<ActionResult>((task) =>
               {
                   return Json(task.Result, JsonRequestBehavior.AllowGet);
               });
            }
        }

     


  • 相关阅读:
    高级前端工程师面试必备(持续更新中)
    用node编写cli工具
    用vscode开发vue应用
    jsbridge的js封装
    react-create-app 构建react项目的流程以及需要注意的地方
    【面试篇】寒冬求职季之你必须要懂的原生JS(中)
    基于vue-cli3.0构建功能完善的移动端架子,主要功能包括
    @vue/cl构建得项目下,postcss.config.js配置,将px转化成rem
    eslint prettier editrorconfig
    数据结构题集--集锦
  • 原文地址:https://www.cnblogs.com/visonme/p/5537190.html
Copyright © 2011-2022 走看看