• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

asp.net mvc源码分析-AsyncController

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

我们前面的讲的都是基于同步的Controller来实现,现在我们来看看基于异步的AsyncController又是如何实现的。

首先看一个demo吧:

 public void IndexAsync()
          {
              //实现异步action加计数1
              FileStream fileStream = new FileStream(@"D:\channel.txt", FileMode.Open);
             byte[] byteArray = new byte[fileStream.Length];
             fileStream.BeginRead(byteArray, 0, (int)fileStream.Length, (IAsyncResult result) =>
              {
                 string content = Encoding.Default.GetString(byteArray);
                 //参数要放在这个字典里面实现向Completed action传递
                 AsyncManager.Parameters["content"] = content;
                 //异步action回调结束
                 fileStream.Close();
            }, null);
         }
        //这个action以Completed为后缀异步action结束后调用的函数,返回值为ActionResult
       public ActionResult IndexCompleted(string content)
         {
             return Content(content);
         }

网上对AsyncController也有些意见

此外还要另外注意几点:

       1.对于异步请求,当发起另外一个线程去处理请求没有返回怎么办,比如抛出异常?框架默认的超时时间是45秒,在45秒到了之后框架会抛出一个System.TimeoutException以中止这个异步请求,我们可以通过[AsyncTimeOut((int duration)]来设置超时时间,还可以通过NoAsyncTimeout或者[AsyncTimeout(Timeout.Infinite)]来设置永不过期。

       2.可以使用AsyncManager.Finish方法来中止所有还未结束的异步操作,进而调用Completed action,如果被强制中止的异步操作还没有成功返回某些参数时,Completed将使用这些参数的默认值(如int为0,string为empty)。

       3.AsyncManager.Sync方法的作用

我喜欢看看源代码,知道这一切都是为什么。我一次做AsyncController我的问题是它是这么调用回调函数的,参数又是如何获取的了。

首先看看AsyncController 的定义:

  public abstract class AsyncController : Controller, IAsyncManagerContainer, IAsyncController 

    public interface IAsyncController : IController {
        IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state);
        void EndExecute(IAsyncResult asyncResult);

    }

   public interface IAsyncManagerContainer {
AsyncManager AsyncManager { get;}
}

这里我们知道AsyncController实现了异步的效果,同时里面还有一个AsyncManager ,我们知道执行Action的一个关键类是ControllerActionInvoker类,在AsyncController应该创建一个和它差不多的类啊?实现这个功能的在这句代码:

  protected override IActionInvoker CreateActionInvoker() {
            return new AsyncControllerActionInvoker();
        }

 public class AsyncControllerActionInvoker : ControllerActionInvoker, IAsyncActionInvoker

从AsyncControllerActionInvoker 的定义我们知道它实现了异步功能。它的结构和我们的ControllerActionInvoker相差不大,在它的GetControllerDescriptor方法中有这么一句:ControllerDescriptor controllerDescriptor = DescriptorCache.GetDescriptor(controllerType, () => newReflectedAsyncControllerDescriptor(controllerType));

ReflectedAsyncControllerDescriptor和ReflectedControllerDescriptor类相差不大,只不过ReflectedControllerDescriptor里面用到了ActionMethodSelector查找参数,而ReflectedAsyncControllerDescriptor用的是AsyncActionMethodSelector查找参数

在AsyncActionMethodSelector的GetActionDescriptorDelegate方法中有点特殊:

        private ActionDescriptorCreator GetActionDescriptorDelegate(MethodInfo entryMethod) {
            // Is this the FooAsync() / FooCompleted() pattern?
            if (IsAsyncSuffixedMethod(entryMethod)) {
                string completionMethodName = entryMethod.Name.Substring(0, entryMethod.Name.Length - "Async".Length) + "Completed";
                MethodInfo completionMethod = GetMethodByName(completionMethodName);
                if (completionMethod != null) {
                    return (actionName, controllerDescriptor) => new ReflectedAsyncActionDescriptor(entryMethod, completionMethod, actionName, controllerDescriptor);
                }
                else {
                    throw Error.AsyncActionMethodSelector_CouldNotFindMethod(completionMethodName, ControllerType);
                }
            }

            // Fallback to synchronous method
            return (actionName, controllerDescriptor) => new ReflectedActionDescriptor(entryMethod, actionName, controllerDescriptor);
        }
  private static bool IsAsyncSuffixedMethod(MethodInfo methodInfo) {
            return methodInfo.Name.EndsWith("Async", StringComparison.OrdinalIgnoreCase);
        }

从这里我们知道我们的方法名应该命名位xxxAsync()->xxxCompleted()这个格式,系统会自己调用对应的回调方法也只有以这种命名了的方法才是真正实现了异步的,不然又返回一个普通的ReflectedActionDescriptor,在这里我们可以猜测ReflectedAsyncActionDescriptor应该是实现了异步模式的

public class ReflectedAsyncActionDescriptor : AsyncActionDescriptor

在ReflectedAsyncActionDescriptor的BeginExecute方法中主要内容如下:

 AsyncManager asyncManager = GetAsyncManager(controllerContext.Controller);
            BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState) {
                // call the XxxAsync() method
                ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(AsyncMethodInfo);
                dispatcher.Execute(controllerContext.Controller, parametersArray); 
// ignore return value from this method
                return asyncResult;
            };
            EndInvokeDelegate<object> endDelegate = delegate(IAsyncResult asyncResult) {
                // call the XxxCompleted() method
                ParameterInfo[] completionParametersInfos = CompletedMethodInfo.GetParameters();
                var rawCompletionParameterValues = from parameterInfo in completionParametersInfos
                                                   select ExtractParameterOrDefaultFromDictionary(parameterInfo,asyncManager.Parameters);
                object[] completionParametersArray = rawCompletionParameterValues.ToArray();
                ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(CompletedMethodInfo);
                object actionReturnValue = dispatcher.Execute(controllerContext.Controller, completionParametersArray);

                return actionReturnValue;
            };
            return AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _executeTag, asyncManager.Timeout);

这里我们就可以确定程序在调用了XxxAsync之后会自动调用XxxCompleted方法,XxxCompleted所需参数的值会从AsyncManager。Parameters中获取。这里面的具体实现还是很复杂了,我们就滤过了吧。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap