Blazor 服务器端项目中的内存泄漏



我做了一个简单的系统来添加和删除EF Core数据库中的文件,如下所示:

  • 添加文件 :

    public async Task AddFile(IFileListEntry file)
    {
    File fileToAdd = await File.GetFileAsync(file);
    _context.Files.Add(fileToAdd);
    _context.SaveChanges();
    }
    
  • IFileListEntry接口获取文件,将文件包含在Stream中:

    public static async Task<File> GetFileAsync(IFileListEntry file)
    {
    using MemoryStream ms = new MemoryStream();
    await file.Data.CopyToAsync(ms);
    File f = new File
    {
    Name = file.Name,
    Type = file.Type,
    Size = file.Size,
    LastModified = file.LastModified,
    Data = ms.ToArray(),
    };
    ms.Dispose();
    return f;
    }
    
  • 删除文件 :

    public void DeleteFile(File file)
    {
    file.Data = new byte[0]; //Test
    _context.Files.Remove(file);
    _context.SaveChanges();
    }
    

添加的所有文件都存储在List中,并从中删除,列表本身包含在.razor文件中(此处未显示,因为我认为这与我的问题无关(,也包含在EF Core数据库中。

数据库上下文_context是通过 depedency 注入获得的,并从类继承DbContext

所以我的问题是:添加和删除文件后,我可以观察到内存泄漏,因为在将文件添加到数据库和列表中后,RAM 处于同一水平。

那我做错了什么?我真的不明白它可能来自哪里,因为MemoryStream在使用后被处理掉,当文件被删除时,我会用一个空的,甚至是null引用替换填充的byte[]。我确保.razor文件中的List是一个新的空列表,我们再次用添加的文件填充该列表。不过我没有测试_context

我认为您的 DI 容器不会释放数据库上下文。

在此处查看数据库上下文文档

上下文的生存期从创建实例时开始,到实例被释放或垃圾回收时结束。如果您希望在块末尾释放上下文控制的所有资源,请使用 using。使用 using 时,编译器会自动创建一个 try/finally 块,并在 finally 块中调用 dispose。

public void UseProducts()
{
using (var context = new ProductContext())
{     
// Perform data access using the context
}
}

如果上下文实例是由依赖项注入容器创建的,则容器通常负责释放上下文。

因此,如果您的 DI 不释放上下文,那么它会保留在内存中,因此看起来您有泄漏。

可能发生的另一件事是,垃圾回收不会发生可预测地检查此处的垃圾回收。因此,可能需要一些时间才能看到释放的内存。

最后一件事:你不需要ms.Dispose();MemoryStream

此类型实现 IDisposable 接口,但实际上没有任何要释放的资源。这意味着不需要通过直接调用 Dispose(( 或使用语言构造(如 using (在 C# 中(或 Using(在 Visual Basic 中((来释放它。

所以MemoryStream不会成为问题。

最新更新