ASP.NET Web API 框架研究 Controller实例的销毁
我们知道项目中创建的Controller,如ProductController都继承自ApiController抽象类,其又实现了接口IDisposable,所以,框架中自动调用Dispose方法来释放其资源。在代表请求的HttpRequestMessage属性字典中,有个Key,“Ms_DisposableRequestResources” ,其值是类型List<IDisposable>,用来存放待释放的资源,回顾下ApiController抽象类的方法ExecuteAsync里的代码片段。

Request.RegisterForDispose(this)是主要代码,我们看下HttpRequestMessage的相关扩展方法,RegisterForDispose注册销毁资源,DisposeRequestResources释放所有资源。
public static class HttpRequestMessageExtensions
{
//注册一个待销毁的资源列表到请求的属性字典中
public static void RegisterForDispose(this HttpRequestMessage request, IDisposable resource)
{
if (request == null)
{
throw Error.ArgumentNull("request");
} if (resource == null)
{
return;
} List<IDisposable> trackedResources = GetRegisteredResourcesForDispose(request); trackedResources.Add(resource);
} //一次性注册多个待销毁的资源列表到请求的属性字典中
public static void RegisterForDispose(this HttpRequestMessage request, IEnumerable<IDisposable> resources)
{
if (request == null)
{
throw Error.ArgumentNull("request");
} if (resources == null)
{
throw Error.ArgumentNull("resources");
} List<IDisposable> trackedResources = GetRegisteredResourcesForDispose(request); foreach (IDisposable resource in resources)
{
if (resource != null)
{
trackedResources.Add(resource);
}
}
} //释放资源列表(RegisterForDispose方法注册)里的所有资源
public static void DisposeRequestResources(this HttpRequestMessage request)
{
if (request == null)
{
throw Error.ArgumentNull("request");
} List<IDisposable> resourcesToDispose;
if (request.Properties.TryGetValue(HttpPropertyKeys.DisposableRequestResourcesKey, out resourcesToDispose))
{
foreach (IDisposable resource in resourcesToDispose)
{
try
{
resource.Dispose();
}
catch
{
// ignore exceptions
}
}
//清空列表
resourcesToDispose.Clear();
}
} //从当前请求中获取所有待销毁的资源的列表
public static IEnumerable<IDisposable> GetResourcesForDisposal(this HttpRequestMessage request)
{
if (request == null)
{
throw Error.ArgumentNull("request");
} return GetRegisteredResourcesForDispose(request);
} //从当前请求中获取所有待销毁的资源的列表
private static List<IDisposable> GetRegisteredResourcesForDispose(HttpRequestMessage request)
{
List<IDisposable> registeredResourcesForDispose;
//从属性字典中,获取指定Key的值
if (!request.Properties.TryGetValue(HttpPropertyKeys.DisposableRequestResourcesKey, out registeredResourcesForDispose))
{
registeredResourcesForDispose = new List<IDisposable>();
request.Properties[HttpPropertyKeys.DisposableRequestResourcesKey] = registeredResourcesForDispose;
}
return registeredResourcesForDispose;
}
}
一、WebHost 模式下的资源销毁
ASP.NET Web API用于“处理请求、回复响应”的 HttpMessageHandler管道是由 HttpControllerHandler创建的,后者根据当前HTTP上下文创建一个表示当前请求的HttpRequestMessage对象并传入这个管道进行处理 。在整个管道完成对请求的处理并最终对请求予以响应之后 ,HttpControllerHandler会负责完成资源释放有关的工作
工作。回顾下HttpControllerHandler,方法的代码:
public class HttpControllerHandler:HttpTaskAsyncHandler
{
//省略其他成员 public HttpControllerHandler(RouteData routeData)
: this(routeData, GlobalConfiguration.DefaultServer)
{
} public override Task ProcessRequestAsync(HttpContext context)
{
return ProcessRequestAsyncCore(new HttpContextWrapper(context));
} internal async Task ProcessRequestAsyncCore(HttpContextBase contextBase)
{
HttpRequestMessage request = contextBase.GetHttpRequestMessage() ?? ConvertRequest(contextBase); // Add route data
request.SetRouteData(_routeData);
CancellationToken cancellationToken = contextBase.Response.GetClientDisconnectedTokenWhenFixed();
HttpResponseMessage response = null; try
{
//创建消息处理管道,并执行
response = await _server.SendAsync(request, cancellationToken);
//异步执行完成
await CopyResponseAsync(contextBase, request, response, _exceptionLogger.Value, _exceptionHandler.Value,
cancellationToken);
}
catch (OperationCanceledException)
{ contextBase.Request.Abort();
}
finally
{
//1.调用方法DisposeRequestResources释放属性字典中的待释放资源
request.DisposeRequestResources();
//2.释放请求消息
request.Dispose();
//3.释放响应消息
if (response != null)
{
response.Dispose();
}
}
}
}
从代码可知道,创建管道并执行完成后,在finally代码块里释放了三种资源,
- 调用方法DisposeRequestResources释放属性字典中的待释放资源
- 请求消息
- 响应消息
二、Self Host模式下的资源销毁
Self Host模式下的请求的监听、接收和响应是通过HttpBinding创建的信道栈来完成的,该信道栈处理的消息类型为HttpMessage,具体代表请求消息和响应消息的HttpMesmge分别是对HttpRequestMessage和Message对象的封装。WCF中表示消息的Message本身就是一个需要最终被释放的对象,在针对它的处理结束之后会调用其Close或 者 Dispose方法对它进行资源释放的工作。再看下代码段
internal sealed class HttpMessage : Message
{
//省略其他成员
protected override void OnClose()
{
base.Close();
if (_request != null)
{
//1.调用DisposeRequestResources,释放属性字典中注册的资源
_request.DisposeRequestResources();
//2.释放请求消息
_request.Dispose();
_request = null;
}
//3.释放响应消息
if (_response != null)
{
_response.Dispose();
_response = null;
}
}
}
internal sealed class Message : IDisposable
{
protected virtual void OnClose()
{
} public void Close()
{
if (this.state != MessageState.Closed)
{
this.state = MessageState.Closed;
//调用OnClose()
this.OnClose();
if (!System.ServiceModel.DiagnosticUtility.ShouldTraceVerbose)
return;
TraceUtility.TraceEvent(TraceEventType.Verbose, , System.ServiceModel.SR.GetString("TraceCodeMessageClosed"), this);
}
else
{
if (!System.ServiceModel.DiagnosticUtility.ShouldTraceVerbose)
return;
TraceUtility.TraceEvent(TraceEventType.Verbose, , System.ServiceModel.SR.GetString("TraceCodeMessageClosedAgain"), this);
}
}
//Dispose模式用法
void IDisposable.Dispose()
{
//调用Close()
this.Close();
}
}
从代码可以知道,在HttpMessage的Dispose方法里,会调用代码也是释放三种资源
- 调用方法DisposeRequestResources释放属性字典中的待释放资源
- 请求消息
- 响应消息
ASP.NET Web API 框架研究 Controller实例的销毁的更多相关文章
- ASP.NET Web API 框架研究 Controller创建 HttpController介绍
对请求进行路由解析以及消息处理管道进行处理后,最后可以从HttpRequestMessage对象的属性字典中获取解析的路由数据,后边我们就可以根据其进行HttpController的创建,从前边几篇可 ...
- ASP.NET Web API 框架研究 Controller创建 HttpController 类型解析 选择 创建
上一篇介绍了HttpController的一些细节,接下来说下HttpController 类型解析.选择和创建.生产HttpController实例的生产线如下图: 一.涉及的类及源码分析 涉及的类 ...
- ASP.NET Web API 框架研究 Controller创建过程与消息处理管道
现在我们从代码角度来看下,从消息处理管道末尾是怎么创建出Controller实例的.消息处理管道末端是一个叫HttpRoutingDispatcher的处理器,其内部完成路由后 ,会把消息派送给其内部 ...
- ASP.NET Web API 框架研究 ASP.NET Web API 路由
ASP.NET Web API 核心框架是一个独立的.抽象的消息处理管道,ASP.NET Web API有自己独立的路由系统,是消息处理管道的组成部分,其与ASP.NET路由系统有类似的设计,都能找到 ...
- ASP.NET Web API 框架研究 Action方法介绍
在根据请求解析出匹配的Controller类型并创建实例后,要在该Controller类型中的众多Action方法中选择与请求匹配的那一个,并执行,然后返回响应. Action方法,其元数据,主要包括 ...
- ASP.NET Web API 框架研究 核心的消息处理管道
ASP.NET Web API 的核心框架是一个由一组HttpMessageHandler有序组成的双工消息处理管道:寄宿监听到请求接受后,把消息传入该管道经过所有HttpMessageHandler ...
- ASP.NET Web API 框架研究 IoC容器 DependencyResolver
一.概念 1.IoC(Inversion of Control),控制反转 即将依赖对象的创建和维护交给一个外部容器来负责,而不是应用本身.如,在类型A中需要使用类型B的实例,而B的实例的创建不是由A ...
- ASP.NET Web API 框架研究 服务容器 ServicesContainer
ServicesContainer是一个服务的容器,可以理解为—个轻量级的IoC容器,其维护着一个服务接口类型与服务实例之间的映射关系,可以根据服务接口类型获取对应的服务实例.构成ASP.NET We ...
- ASP.NET Web API 框架研究 Self Host模式下的消息处理管道
Self Host模式下的ASP.NET Web API与WCF非常相似,都可以寄宿在任意类型的托管应用程序中,宿主可以是Windows Form .WPF.控制台应用以及Windows Servic ...
随机推荐
- HDU 4455.Substrings
Substrings Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- Spring ApplicationContext(六)BeanPostProcessor
Spring ApplicationContext(六)BeanPostProcessor 产生回顾一下 ApplicationContext 初始化的几个步骤:第一步是刷新环境变量:第二步是刷新 b ...
- Spring 系列教程之自定义标签的解析
Spring 系列教程之自定义标签的解析 在之前的章节中,我们提到了在 Spring 中存在默认标签与自定义标签两种,而在上一章节中我们分析了 Spring 中对默认标签的解析过程,相信大家一定已经有 ...
- 使用vmware安装ubuntu不能上网
桌面版的话,进入桌面后还可以配置,服务版,我是在安装过程中提示的网络配置时候按照下面的方法手动配置的 安装虚拟机时候要安装网络服务,有的虚拟机在安装过程中可能已经安装好了,主机保持VMware NAT ...
- 过河卒(NOIP2002)
题目链接:过河卒 直接模拟?会T掉60分. 所以我们可以采用递推,怎么想到的? 因为卒子只能向下或向右走,所以走到一个点的方法数,等于走到它上面点的方法数加上走到它左边点的方法数,这样就可以地推了. ...
- UDDI
什么是 UDDI? UDDI 是一个独立于平台的框架,用于通过使用 Internet 来描述服务,发现企业,并对企业服务进行集成. UDDI 指的是通用描述.发现与集成服务 UDDI 是一种用于存储有 ...
- syslog系统日志、事件日志分析、EventLog Analyzer
syslog系统日志.事件日志分析.EventLog Analyzer Eventlog Analyzer是用来分析和审计系统及事件日志的管理软件,能够对全网范围内的主机.服务器.网络设备.数据库以及 ...
- Python开课复习7
操作系统 操作系统把复杂的硬件操作封装成简单的接口给用户/应用程序使用,其中文件就是操作系统提供给应用程序来操作硬盘虚拟概念,用户或应用程序通过操作文件,可以将自己的数据永久保存下来. #1. 打开文 ...
- Codeforces 1111 简要题解
文章目录 A题 B题 C题 D题 E题 传送门 A题 传送门 题意简述:把262626个英文字母分成两类A,BA,BA,B,AAA类字符可以转成AAA类字符,BBB类字符可以转成BBB类字符,问给出的 ...
- 2018.11.07 bzoj2751: [HAOI2012]容易题(easy)(组合数学)
传送门 组合数学一眼题. 感觉一直做这种题智商会降低. 利用组合数学的分步计数原理. 只用关心每个数不被限制的取值的总和然后乘起来就可以了. 对于大部分数都不会被限制,总和都是n(n+1)2\frac ...