可以在关闭后为另一个对象调用 Dispose() 方法的泛型流

本文关键字:Dispose 方法 泛型 调用 一个对象 | 更新日期: 2023-09-27 18:34:58

这是一个非常简单的示例,如何将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的现有实现?

可以在关闭后为另一个对象调用 Dispose() 方法的泛型流

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

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

关于这个话题,你可以在这里找到达林·季米特洛夫更好、更详细的答案。