【问题标题】:c#: Return a stream on Web API corec#:在 Web API 核心上返回一个流
【发布时间】: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


【解决方案1】:

您的第一种方法没有任何问题。如果代码抛出(在您的方法中或在 asp.net 框架中),那么最终流和编写器将被垃圾收集。

如果没有发生任何事情,那么File 类将在内存流上调用Dispose,但由于这只是byte 数组的包装器,因此在垃圾收集器启动之前不会真正发生任何事情,所以无论哪种方式你的代码很好。

【讨论】:

  • 我认为避免处理未使用的蒸汽是一种不好的做法。取决于连接到我的 GC 声音。你确定吗?
  • @No1Lives4Ever - 这完全取决于上下文。在这种情况下很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-01
  • 2020-07-01
  • 1970-01-01
  • 2020-05-16
  • 2017-12-31
  • 2017-01-30
  • 1970-01-01
相关资源
最近更新 更多