Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET MVC/WEB API文件上载:上载后未释放内存_C#_Asp.net Mvc_File Upload_Asp.net Web Api_Memory Leaks - Fatal编程技术网

C# ASP.NET MVC/WEB API文件上载:上载后未释放内存

C# ASP.NET MVC/WEB API文件上载:上载后未释放内存,c#,asp.net-mvc,file-upload,asp.net-web-api,memory-leaks,C#,Asp.net Mvc,File Upload,Asp.net Web Api,Memory Leaks,我正在调查一个用户上载文件的项目中可能存在的内存泄漏问题。这些文件通常是用于其他软件的.zip或.exe压缩文件。文件的平均大小为80MB 有一个MVC应用程序,它具有上载文件(视图)的界面。此视图向控制器内的操作发送POST请求。此控制器操作使用与以下内容类似的MultipartFormDataContent获取文件: 在操作内部,我获取文件并将其转换为字节数组。转换后,我用byte[]数组向API发送post请求 以下是实现此功能的MVC应用程序代码: [HttpPost] publ

我正在调查一个用户上载文件的项目中可能存在的内存泄漏问题。这些文件通常是用于其他软件的.zip或.exe压缩文件。文件的平均大小为80MB

有一个MVC应用程序,它具有上载文件(视图)的界面。此视图向控制器内的操作发送POST请求。此控制器操作使用与以下内容类似的MultipartFormDataContent获取文件:

在操作内部,我获取文件并将其转换为字节数组。转换后,我用byte[]数组向API发送post请求

以下是实现此功能的MVC应用程序代码:

[HttpPost]
    public async Task<ActionResult> Create(ReaderCreateViewModel model)
    {
        HttpPostedFileBase file = Request.Files["Upload"];

        string fileName = file.FileName;

        using (var client = new HttpClient())
        {
            using (var content = new MultipartFormDataContent())
            {                   
                using (var binaryReader = new BinaryReader(file.InputStream))
                {
                    model.File = binaryReader.ReadBytes(file.ContentLength);
                }

                var fileContent = new ByteArrayContent(model.File);
                fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
                {
                    FileName = file.FileName
                };
                content.Add(fileContent);

                var requestUri = "http://localhost:52970/api/upload";
                HttpResponseMessage response = client.PostAsync(requestUri, content).Result;

                if (response.IsSuccessStatusCode)
                {                       
                    return RedirectToAction("Index");
                }
            }
        }

        return View("Index", model);
    }
内存使用量从70MB+或-增加到175mb+或-甚至在发送和完成请求后,内存永远不会释放。如果我一直上传文件,内存就会一直增加,直到服务器完全关闭

我们不能将文件直接从多部分表单发送到API,因为我们需要在之前发送和验证一些数据(业务需求/规则)。经过研究,我提出了这种方法,但内存泄漏问题与我有关

我错过什么了吗?垃圾收集器应该立即收集内存吗?在所有一次性对象中,我都使用“使用”语法,但它没有帮助

我也很好奇这种上传文件的方法。我应该换一种方式吗


为了澄清,API与MVC应用程序分离(每个应用程序都托管在IIS中一个单独的网站上),并且都在C#中。

1。垃圾收集器是否应该立即收集内存?

垃圾收集器不会立即释放内存,因为这是一个耗时的操作。当发生垃圾回收时,所有应用程序的托管线程都将暂停。这会引入不必要的延迟。因此,垃圾收集器只是偶尔根据复杂的算法进行操作

2。在所有一次性对象中,我都使用了“使用”语法,但没有任何帮助。

using
语句处理供应有限的非托管资源 (通常与IO相关,如文件句柄、数据库和网络连接)。因此,此语句不影响垃圾收集

3。我错过了什么吗?

在使用
ByteArrayContent
对原始字节数组进行包装后,似乎不需要它。包装后不清理
model.File
,数组最终可能会传递到索引视图

我将替换:

using(var binaryReader = new BinaryReader(file.InputStream)) {
    model.File = binaryReader.ReadBytes(file.ContentLength);
}
var fileContent = new ByteArrayContent(model.File);
与:

避免需要明确地清理
model.File

4。如果我一直上传文件,内存就会一直增加,直到服务器完全关闭。

如果您的文件平均为80MB,那么它们最终将位于大型对象堆上。堆不会自动压缩,通常不会进行垃圾收集。在您的例子中,大型对象堆似乎无限期地增长(这是可能发生的)

如果您正在使用(或可以升级到).NET 4.5.1或更新版本,则可以通过以下设置强制压缩大型对象堆:

System.Runtime.GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
每次您希望在下一次完全垃圾收集时安排大型对象堆压缩时,都需要调用这一行代码

您还可以通过调用以下命令强制立即压缩:

System.Runtime.GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
System.GC.Collect();
然而,如果您需要释放大量内存,这将是一个在时间方面代价高昂的操作

System.Runtime.GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
System.Runtime.GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
System.GC.Collect();