gpt4 book ai didi

c# - ASP.NET MVC/WEB API 文件上传 : Memory not being deallocated after upload

转载 作者:行者123 更新时间:2023-11-30 12:25:10 25 4
gpt4 key购买 nike

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

有一个 MVC 应用程序具有上传文件的界面( View )。此 View 将 POST 请求发送到 Controller 中的操作。此 Controller 操作使用类似于此的 MultipartFormDataContent 获取文件:Sending binary data along with a REST API request还有这个:WEB API FILE UPLOAD, SINGLE OR MULTIPLE FILES

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

这是执行此操作的 MVC APP 代码:

[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);
}

在调查使用多种内存工具后,例如:Best Practices No. 5: Detecting .NET application memory leaks我发现在这一行将文件转换为字节数组后:

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

内存使用量从 70MB + 或 - 增加到 175mb + 或 - 并且即使在发送并完成请求后,内存也永远不会被释放。如果我继续上传文件,内存会一直增加,直到服务器完全宕机。

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

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

我也很好奇这种上传文件的方法。我应该以不同的方式做吗?

澄清一下,API 与 MVC 应用程序是分开的(每个应用程序都托管在 IIS 中的单独网站上),并且全部使用 C#。

最佳答案

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

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

<强>2。在所有一次性对象中,我都使用“使用”语法,但它没有帮助。

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

<强>3。我错过了什么吗?

ByteArrayContent 包装后,您似乎不需要原始字节数组。包装后不清理 model.File,数组最终会传递给 Index View 。

我会替换:

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

与:

ByteArrayContent fileContent = null;
using(var binaryReader = new BinaryReader(file.InputStream)) {
fileContent = new ByteArrayContent(binaryReader.ReadBytes(file.ContentLength));
}

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

<强>4。如果我继续上传文件,内存只会不断增加,直到服务器完全关闭。

如果您的文件平均为 80MB,它们最终会位于大型对象堆中。堆不会自动压缩,通常不会被垃圾回收。在您的情况下,大对象堆看起来会无限增长(这可能会发生)。

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

System.Runtime.GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;

每次您想要在下一次完全垃圾回收时安排大对象堆压缩时,您都需要调用这行代码。

你也可以通过调用强制立即压缩:

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

但是,如果您需要释放大量内存,这将是一项耗时的操作。

关于c# - ASP.NET MVC/WEB API 文件上传 : Memory not being deallocated after upload,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32017300/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com