【问题标题】:Generic Stream that can call Dispose() method for another object after closing关闭后可以为另一个对象调用 Dispose() 方法的通用 Stream
【发布时间】:2013-10-12 14:11:39
【问题描述】:

这是一个非常简单的示例,我如何将 Stream 返回到 ASP.NET MVC:

public ActionResult DownloadData(...)
{
    using(var lib = new SomeLibrary())
    {
        // do some stuff...

        var stream = new MemoryStream();
        lib.SaveAs(stream);

        stream.Position = 0;

        return File(stream, "contenttype", "filename");
    }
}

问题是MemoryStream 将被分配在大堆对象区域中,而在 32 位系统上它会很快导致OutOfMemoryException,因为 RAM 碎片会阻止分配大内存块,即使有足够的内存也是如此.在 64 位系统上,这种方法也很慢。

我想要的只是返回一个流,类似于这个

public ActionResult DownloadData(...)
{
    using(var lib = new SomeLibrary())
    {
        // do some stuff...
        return File(lib.Stream, "contenttype", "filename");
    }
}

但是,using 语句将在我的数据返回之前调用.Dispose()。如果我完全删除using 语句,那么库将锁定资源,直到垃圾收集器清理内存。

我认为最好的解决方案是使用通用的Stream,它只复制源流并在最后调用.Dispose()

public ActionResult DownloadData(...)
{
    var lib = new SomeLibrary()

    try
    {
        // do some stuff...

        var stream = new CopyStream(lib.Stream, lib);

        return File(stream, "contenttype", "filename");
    }
    catch(Exception)
    {
        lib.Dispose();
        throw;
    }
}

通用流在关闭后应该为第二个参数lib调用.Dispose()

在 .NET 或 NuGet 中是否存在此类Stream 的现有实现?

【问题讨论】:

  • 完全不清楚您为什么要寻找定制的东西。 Stream 类已经继承了 IDisposable 并实现了一次性模式。您当然应该使用 using 关键字来处理它,就像处理任何流一样。否则它对内存使用没有任何影响,这是由垃圾收集器管理的,而不是你的程序。

标签: c# stream


【解决方案1】:

也许我不完全了解您需要什么,但在您的情况下,不需要自己处理流(使用显式 Dispose() 调用或使用 using 关键字)。

来自 ASP MVC 控制器的 File 帮助器方法旨在返回流:它创建一个 FileStreamResult 负责处理封装的流,并在其工作完成时执行此操作。

关于这个话题,您可以在here 中找到 Darin Dimitrov 更好、更详细的答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多