c#:返回Web API核心上的流

c#:返回Web API核心上的流,c#,asp.net,asp.net-web-api,asp.net-core-mvc,C#,Asp.net,Asp.net Web Api,Asp.net Core Mvc,我有一个用C#(v2.2)编写的ASP.NET web API服务器。我公开的方法之一,创建MemoryStream并向其中添加数据。最后,使用返回文件(ms)方法返回它 我的代码如下所示: [HttpGet] [Route("my-endpoint")] public async Task<ActionResult> TestMe() { MemoryStream ms = new MemoryStream(); StreamWriter sw = new Stre

我有一个用C#(v2.2)编写的ASP.NET web API服务器。我公开的方法之一,创建
MemoryStream
并向其中添加数据。最后,使用
返回文件(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");
}
[HttpGet]
[路线(“我的终点”)]
公共异步任务TestMe()
{
MemoryStream ms=新的MemoryStream();
StreamWriter sw=新StreamWriter(毫秒);
wait sw.WriteLineAsync($“A,B,C”)。configurewait(false);
wait sw.WriteLineAsync($“1,2,3”).configurewait(false);
wait sw.FlushAsync().configurewait(false);
Seek女士(0,SeekOrigin.Begin);
返回文件(ms,“应用程序/csv”);
}
这里的问题是,这段代码不能确定地处理内存中的所有流。如果一切正常,则ASP.NET代码将关闭流。如果抛出异常,则不会释放流

我认为实现它的正确方法是(此代码不起作用):

[HttpGet]
[路线(“我的终点”)]
公共异步任务TestMe()
{
使用(MemoryStream ms=new MemoryStream())
使用(StreamWriter sw=新StreamWriter(ms))
{
wait sw.WriteLineAsync($“A,B,C”)。configurewait(false);
wait sw.WriteLineAsync($“1,2,3”).configurewait(false);
wait sw.FlushAsync().configurewait(false);
Seek女士(0,SeekOrigin.Begin);
返回文件(ms,“应用程序/csv”);
}
}
这里的问题是当我们离开函数时(在
return
行)。然后,流将在返回到客户端之前被处理


如何使我的代码安全地工作?

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


如果没有任何结果,那么
文件
类将调用内存流上的
Dispose
,但由于这只是
字节
数组上的一个包装,在垃圾收集器启动之前,不会发生任何事情,因此无论哪种方式,您的代码都没有问题。

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


如果没有任何结果,则
文件
类将调用内存流上的
Dispose
,但由于这只是
字节
数组上的包装,在垃圾收集器启动之前,不会发生任何事情,因此,无论哪种方式,您的代码都很好。

当您谈到抛出异常时,您是指在
TestMe
方法中还是在asp.net框架中?MemoryStream只是
字节[]
上的包装器。您不必担心如何处理它。
ConfigureAwait(false)
在ASP.NET核心应用程序中无效,因为没有可返回的同步上下文。您不会像在桌面应用程序或ASP.NET中那样出现死锁application@Sean,我担心我的代码(testme方法)。@No1Lives4Ever-没必要担心。您的方法只是分配内存,而不是像文件这样的底层资源,因此如果出现问题,GC将收集内存。即使您正在调用
Dispose
也不会发生任何事情,因为它只是您分配的内存。当您谈到抛出异常时,您是指在
TestMe
方法中还是在asp.net框架中?MemoryStream只是
字节[]
上的包装器。您不必担心如何处理它。
ConfigureAwait(false)
在ASP.NET核心应用程序中无效,因为没有可返回的同步上下文。您不会像在桌面应用程序或ASP.NET中那样出现死锁application@Sean,我担心我的代码(testme方法)。@No1Lives4Ever-没必要担心。您的方法只是分配内存,而不是像文件这样的底层资源,因此如果出现问题,GC将收集内存。即使您正在调用
Dispose
也不会发生任何事情,因为这只是您分配的内存。我认为避免处理未使用的数据流是一种不好的做法。取决于我听到的GC声音。你确定吗?@No1Lives4Ever-这取决于上下文。在这种情况下没关系。我认为避免处理未使用的蒸汽是一种不好的做法。取决于我听到的GC声音。你确定吗?@No1Lives4Ever-这取决于上下文。这样就可以了。
[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");
    }
}