Aspnet MVC 异步调用

Posted Vison+

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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);
           });
        }
    }

 

 

 


 

以上是关于Aspnet MVC 异步调用的主要内容,如果未能解决你的问题,请参考以下文章

ASP.net MVC 代码片段问题中的 Jqgrid 实现

带有aspnet mvc的ajax永远无法工作

从片段中调用分离的异步任务类

MVC2 一次异步调用,多次异步更新

如何在 aspnet 身份中进行会话管理?

MVC Javascript xmlhttprequest 调用异步方法