C# MemoryStream作为ActionResult返回时是否会自动处理?

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

我习惯于将“using”语句与memoryStream结合使用。这是一个不需要使用“using”语句的场景吗?或者在“using”语句中调用return是否有效

编辑:

出于我的目的,我发现引入“using”语句不起作用(抛出ObjectDisposedException)。以下是我在客户端对其所做的操作:

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);
    }
}