【发布时间】: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 关键字来处理它,就像处理任何流一样。否则它对内存使用没有任何影响,这是由垃圾收集器管理的,而不是你的程序。