c# - 在动作方法中抛出 HttpResponseException 时处理 HttpResponseMessage 及其内容
问题描述
我的问题的来源是以下代码,它是Microsoft 文档中包含的用于在 asp.net web api 中处理异常的代码片段的一部分:
var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
{
Content = new StringContent(string.Format("No product with ID = {0}", id)),
ReasonPhrase = "Product ID Not Found"
};
throw new HttpResponseException(resp);
两者都HttpResponseMessage
实现StringContent
了IDisposable
接口,但是上面的代码中没有一个调用方法IDisposable.Dispose
。
这是一个问题吗?不处理这些对象是否有任何副作用?
根据这篇文章,一个可能的解决方案可能是将上面的代码更改为以下代码:
var content = new StringContent(string.Format("No product with ID = {0}", id));
var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
{
Content = content,
ReasonPhrase = "Product ID Not Found"
};
this.Request.RegisterForDispose(content);
this.Request.RegisterForDispose(resp);
throw new HttpResponseException(resp);
这真的有必要吗,还是可以避免这种情况(根据 Microsoft 文档中显示的内容)?
解决方案
检查HttpResponseMessage.CS 的 Microsoft 源:
protected virtual void Dispose(bool disposing)
{
// The reason for this type to implement IDisposable is that it contains instances of
// types that implement IDisposable (content).
if (disposing && !_disposed)
{
_disposed = true;
if (_content != null)
{
_content.Dispose();
}
}
}
content
属于 HttpContent 类型。检查HttpContent.cs 的 Microsoft 源代码:
protected override void Dispose(bool disposing)
{
Debug.Assert(_buffer != null);
ArrayPool<byte>.Shared.Return(_buffer);
_buffer = null;
base.Dispose(disposing);
}
ArrayPool的评论说:
/// Renting and returning buffers with an <see cref="ArrayPool{T}"/> can increase performance
/// in situations where arrays are created and destroyed frequently, resulting in significant
/// memory pressure on the garbage collector.
检查 ArrayPool 的源代码会产生这个可爱的宝石:
/// <summary>
/// Retrieves a shared <see cref="ArrayPool{T}"/> instance.
/// </summary>
/// <remarks>
/// The shared pool provides a default implementation of <see cref="ArrayPool{T}"/>
/// that's intended for general applicability. It maintains arrays of multiple sizes, and
/// may hand back a larger array than was actually requested, but will never hand back a smaller
/// array than was requested. Renting a buffer from it with <see cref="Rent"/> will result in an
/// existing buffer being taken from the pool if an appropriate buffer is available or in a new
/// buffer being allocated if one is not available.
/// </remarks>
public static ArrayPool<T> Shared
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return Volatile.Read(ref s_sharedInstance) ?? EnsureSharedCreated(); }
}
ArrayPool
不使用WeakReference
s 或任何类似机制来确保正确处置。如果您从 租用缓冲区ArrayPool.Shared
,则必须将其归还,否则会导致内存泄漏。
所以,是的,我想说尊重IDisposable
在这里非常重要。
推荐阅读
- r - 通过应用缺失值调用均值和中值函数的不同结果
- c# - Automapper:将此设置为属性
- javascript - 问题 - 反应组件状态中的可选字段
- webpack - Webpack 字体在构建时在错误的目录中查找
- android - 我有来自 geojson 的多个地图图层。需要从每一个中获取一个点击事件
- javascript - 如何使用来自 JS 的两个 ID?
- reactjs - React - 文件夹结构
- react-native - 在我的反应原生项目中显示模态时显示吐司?
- python - 使用 python 运行 yamllint 命令行
- python - 迭代中的最后一个值被保存在 python 中