安全地将StreamReader与HttpContent.ReadAsStreamAsync()结合使用,而无需关闭基础流

时间:2019-06-21 20:58:55

标签: streamreader httpcontent

我有多个属性类,它们需要访问HttpContent(位于HttpActionContext的{​​{1}}中)中的数据,但是我在确定最佳方法时遇到了问题做吧。我考虑过在HttpRequstMessage上使用ReadAsStringAsync方法,但是似乎我需要访问HttpContent才能首先将位置设置为0。

幼稚的方式似乎只是用Stream语句将StreamReader包裹在基本流中,如下所示:

using

这对于执行的第一个属性效果很好,但是随后执行的每个后续属性都会因public override void OnActionExecuting(HttpActionContext actionContext) { string rawJson; using (StreamReader streamReader = new StreamReader(actionContext.Request.Content.ReadAsStreamAsync().Result)) { streamReader.BaseStream.Position = 0; rawJson = streamReader.ReadToEnd(); } // etc } 而被抛出异常。

这是可行的替代方法,但我真的很想知道执行此操作的最佳方法。

1:将actionContext.Request.Content.ReadAsStreamAsync()包裹在基本流中,切勿丢弃。

StreamReader

这对每个属性都适用,但是我担心我可能由于不处理public override void OnActionExecuting(HttpActionContext actionContext) { StreamReader streamReader = new StreamReader(actionContext.Request.Content.ReadAsStreamAsync().Result); streamReader.BaseStream.Position = 0; string rawJson = streamReader.ReadToEnd(); // etc } 而泄漏了内存

2:将基本流复制到StreamReader并用MemoryStream包装。

StreamReader

这对每个属性都适用,但是大量代码,可能效率不高

3:将基本流的位置设置为0,然后调用public override void OnActionExecuting(HttpActionContext actionContext) { MemoryStream memoryStream = new MemoryStream(); Stream s = actionContext.Request.Content.ReadAsStreamAsync().Result; s.Position = 0; s.CopyTo(memoryStream); string rawJson; using (StreamReader streamReader = new StreamReader(memoryStream)) { streamReader.BaseStream.Position = 0; rawJson = streamReader.ReadToEnd(); } // etc }

ReadAsStringAsync

这对每个属性都适用,但是效率可能较低

那么,有没有一种最佳的方式来做到这一点而又不会泄漏内存?

1 个答案:

答案 0 :(得分:0)

使用使流保持开放状态的流读取器-由于您不拥有流的所有权,因此它仍属于HTTP操作内容的范围。

public StreamReader (System.IO.Stream stream, System.Text.Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen);

Constructor with the option to leave the stream open

由于可能出现死锁,在同步上下文中也使用.Result来完成异步调用是有风险的。尝试将您的方法重构为异步方法。