C# MemoryStream作为ActionResult返回时是否会自动处理?
我习惯于将“using”语句与memoryStream结合使用。这是一个不需要使用“using”语句的场景吗?或者在“using”语句中调用return是否有效 编辑: 出于我的目的,我发现引入“using”语句不起作用(抛出ObjectDisposedException)。以下是我在客户端对其所做的操作:C# MemoryStream作为ActionResult返回时是否会自动处理?,c#,jquery,asp.net-mvc,using,memorystream,C#,Jquery,Asp.net Mvc,Using,Memorystream,我习惯于将“using”语句与memoryStream结合使用。这是一个不需要使用“using”语句的场景吗?或者在“using”语句中调用return是否有效 编辑: 出于我的目的,我发现引入“using”语句不起作用(抛出ObjectDisposedException)。以下是我在客户端对其所做的操作: public ActionResult CustomChart(int reportID) { Chart chart = new Chart(); // Save the
public ActionResult CustomChart(int reportID)
{
Chart chart = new Chart();
// Save the chart to a MemoryStream
var imgStream = new MemoryStream();
chart.SaveImage(imgStream);
imgStream.Seek(0, SeekOrigin.Begin);
// Return the contents of the Stream to the client
return File(imgStream, "image/png");
}
以下是处理流的有效代码。如果使用将其包含在
块中,则返回时将自动调用MemoryStream.Dispose()
方法
$('#ReportTest').bind('load', function () {
$('#LoadingPanel').hide();
$(this).unbind('load');
}).bind('error', function () {
$('#LoadingPanel').hide();
$(this).unbind('error');
}).attr('src', '../../Chart/CustomChart?ReportID=' + settings.id);
通过将对象放入try
块中,然后在finally块中调用Dispose
,可以获得相同的结果。事实上,根据MSDN文档,编译器就是这样翻译using语句的。在try..finally
块中,即使try
通过return
退出,也将始终执行finally
编译器将使用
块将转换为以下内容:
public ActionResult CustomChart(int reportID)
{
Chart chart = new Chart();
using (var imgStream = new MemoryStream()) {
chart.SaveImage(imgStream);
imgStream.Seek(0, SeekOrigin.Begin);
return File(imgStream, "image/png");
}
}
MemoryStream作为ActionResult返回时是否会自动处理
是的,MVC(至少版本3)将为您清理它。您可以使用FileStreamResult
中的WriteFile
方法:
MemoryStream imgStream = new MemoryStream();
try
{
chart.SaveImage(imgStream);
imgStream.Seek(0, SeekOrigin.Begin);
return File(imgStream, "image/png");
}
finally
{
if (imgStream != null)
((IDisposable)imgStream).Dispose();
}
行using(FileStream){
将把流放在using块中,从而在它将内容写入Http响应时处理它
您还可以通过创建一个虚拟流来验证此行为:
protected override void WriteFile(HttpResponseBase response) {
// grab chunks of data and write to the output stream
Stream outputStream = response.OutputStream;
using (FileStream) {
byte[] buffer = new byte[_bufferSize];
while (true) {
int bytesRead = FileStream.Read(buffer, 0, _bufferSize);
if (bytesRead == 0) {
// no more data
break;
}
outputStream.Write(buffer, 0, bytesRead);
}
}
}
因此MVC将处理它。肖恩:不要使用“using”,因为它将处理对象。让MVC访问已处理的对象。因此出现异常(服务器错误)您遇到的当然是ObjectDisposedException。以前发布的WriteFile函数会为您处理该对象。在这种情况下不需要MemoryStream。您可以通过创建如下自定义ActionResult来避免它:
public class DummyStream : MemoryStream
{
protected override void Dispose(bool disposing)
{
Trace.WriteLine("Do I get disposed?");
base.Dispose(disposing);
}
}
在处理实现IDisposable的类时使用“using”语句总是一个好主意,不管您是否相信ASP.NET会在您之后清理干净
do with the stream?通常创建流的对象也应该处理流。在这种情况下,您将负责处理流。@GeorgeStocker将处理dispose()
方法甚至被调用?我认为在调用return
后,它不会使用块来完成。@Shark dispose最终在中被调用,所以是的-它会被调用。dispose
一次性对象是一种很好的做法。但是对于MemoryStream
来说,唯一能做的事情就是防止你不需要读/写它。所以你当前的实现工作得很好。这会不会把流从文件对象下面拉出来?@LasseV.Karlsen这也是我想知道的。如果它不…为什么它不?:)文件在这里不是构造函数,它是控制器上的一个方法。我只是在我的应用程序中试用了它。介绍f using语句不适用于我的应用程序。我在尝试渲染图像文件时出现内部服务器错误。我不建议这样做:它将在返回流之前关闭流,您将收到一个错误。假设您返回的流带有要在对话框上显示的pdf,您将收到“无法访问关闭流错误”如果您将返回值放在using子句中\谢谢您给出了明确的答案。:)…有趣的是,如果我在应用程序中使用“using”语句,我会生成一个内部服务器错误。@SeanAnderson您是否能够获得堆栈跟踪和异常?这取决于流;它可能不喜欢被处理两次。当render被调用为f时或者我被告知流无效的页面。它只是不喜欢这么早就被GC’ed。晚了几年……但我把接受的答案移了过来。抱歉耽搁了!实际上相当不错的解决方案!看起来它还可以保存一个缓冲区副本。(可能取决于让图表保持那么长时间的活力有多重要)
public class ChartResult : ActionResult
{
private Chart _chart;
public ChartResult(Chart chart)
{
if (chart == null)
throw new ArgumentNullException("chart");
_chart = chart;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = "image/png";
response.BufferOutput = false;
_chart.ImageType = ChartImageType.Png;
_chart.SaveImage(response.OutputStream);
}
}