简体   繁体   中英

Memory leak in Blazor Server-side project

I made a simple system to add and delete file from an EF Core database like this :

  • Add a file :

     public async Task AddFile(IFileListEntry file) { File fileToAdd = await File.GetFileAsync(file); _context.Files.Add(fileToAdd); _context.SaveChanges(); }
  • Get the file from an IFileListEntry interface, containing the file into a 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; }
  • Remove a file :

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

All the files added are stored into a List , and deleted from it, and the list itself is contained into .razor file (not shown here as I think it's irrelavant to my problem), and also in an EF Core database.

The database context _context is obtained through depedency injection and inherits from DbContext class.

So my problem is : after adding and deleting a file, I can observe a memory leak as the RAM is at the same level after the addition of the file into the database and the list.

So what I'm doing wrong ? I really can't understand where it could possibly come from, as the MemoryStream is disposed after its use, and when the file is deleted, I replace the filled byte[] by an empty one, or even a null reference. I made sure the List in my .razor file is a new empty list that we fill up again with the files added. I didn't test for the _context though.

I think that your DI container does not dispose the dbcontext.

Check the dbcontext documentation here

The lifetime of the context begins when the instance is created and ends when the instance is either disposed or garbage-collected. Use using if you want all the resources that the context controls to be disposed at the end of the block. When you use using, the compiler automatically creates a try/finally block and calls dispose in the finally block.

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

If the context instance is created by a dependency injection container, it is usually the responsibility of the container to dispose the context.

So if your DI does not dispose the context, then it remains in memory and thus, it looks like you have a leak.

Another thing that may occur, is that the Garbage Collection does not occur predictably check garbage collection here . So it might take some time to see the freed memory.

One last thing: You don't need to ms.Dispose(); MemoryStream

This type implements the IDisposable interface, but does not actually have any resources to dispose. This means that disposing it by directly calling Dispose() or by using a language construct such as using (in C#) or Using (in Visual Basic) is not necessary.

So the MemoryStream would not be the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM