【发布时间】:2020-03-10 12:24:20
【问题描述】:
我有一个用 C# (v2.2) 编写的 ASP.NET Web API 服务器。我公开的方法之一,创建MemoryStream 并向其中添加数据。最后用return File(ms)方法返回。
我的代码如下所示:
[HttpGet]
[Route("my-endpoint")]
public async Task<ActionResult> TestMe()
{
MemoryStream ms = new MemoryStream();
StreamWriter sw = new StreamWriter(ms);
await sw.WriteLineAsync($"A,B,C").ConfigureAwait(false);
await sw.WriteLineAsync($"1,2,3").ConfigureAwait(false);
await sw.FlushAsync().ConfigureAwait(false);
ms.Seek(0, SeekOrigin.Begin);
return File(ms, "application/csv");
}
这里的问题是这段代码肯定不会从内存中释放所有流。如果一切正常,则流将由 ASP.NET 代码关闭。如果抛出异常,则不会释放流。
我认为实现它的正确方法是(此代码不起作用):
[HttpGet]
[Route("my-endpoint")]
public async Task<ActionResult> TestMe()
{
using (MemoryStream ms = new MemoryStream())
using (StreamWriter sw = new StreamWriter(ms))
{
await sw.WriteLineAsync($"A,B,C").ConfigureAwait(false);
await sw.WriteLineAsync($"1,2,3").ConfigureAwait(false);
await sw.FlushAsync().ConfigureAwait(false);
ms.Seek(0, SeekOrigin.Begin);
return File(ms, "application/csv");
}
}
这里的问题是当我们离开函数时(在return 行)。然后,流将在返回给客户端之前被释放。
如何让我的代码安全运行?
【问题讨论】:
-
当您谈到抛出异常时,您是指在
TestMe方法中还是在asp.net 框架中? -
MemoryStream 只是
byte[]的包装器。您不必担心丢弃它。 -
ConfigureAwait(false)在 ASP.NET Core 应用程序中毫无用处,因为没有可返回的同步上下文。您不会像在桌面应用程序或 ASP.NET 应用程序中那样遇到死锁 -
@Sean,我很担心我的代码(testme 方法)。
-
@No1Lives4Ever - 无需担心。您的方法只是分配内存,而不是文件等底层资源,因此如果出现问题,GC 将收集内存。即使您调用
Dispose,也没有真正发生任何事情,因为它只是您分配的内存。
标签: c# asp.net asp.net-web-api asp.net-core-mvc