Утечка памяти в Blazor-проекте на стороне сервера - PullRequest
2 голосов
/ 06 января 2020

Я создал простую систему для добавления и удаления файла из базы данных 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 получен путем внедрения зависимостей и наследуется от DbContext class.

Поэтому моя проблема: после добавления и удаления файла я могу наблюдайте утечку памяти, поскольку ОЗУ находится на том же уровне после добавления файла в базу данных и список.

Так что я делаю не так? Я действительно не могу понять, откуда он может появиться, так как MemoryStream удаляется после его использования, и когда файл удаляется, я заменяю заполненный byte[] на пустой, или даже ссылку null , Я убедился, что List в моем .razor файле - это новый пустой список, который мы снова заполняем добавленными файлами. Я не проверял _context.

1 Ответ

2 голосов
/ 06 января 2020

Я думаю, что ваш DI-контейнер не располагает dbcontext.

Проверьте документацию по dbcontext здесь

Время жизни контекста начинается, когда экземпляр создается и заканчивается, когда экземпляр удаляется или собирается мусором. Используйте using, если вы хотите, чтобы все ресурсы, которыми управляет контекст, располагались в конце блока. Когда вы используете using, компилятор автоматически создает блок try / finally и вызывает dispose в блоке finally.

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

Если экземпляр контекста создается контейнером внедрения зависимостей, он Обычно контейнер несет ответственность за удаление контекста.

Так что, если ваш DI не располагает контекстом, он остается в памяти и, таким образом, похоже, что у вас есть утечка.

Еще одна вещь, которая может произойти, это то, что сборка мусора не происходит предсказуемо проверьте сборку мусора здесь . Поэтому может потребоваться некоторое время, чтобы увидеть освобожденную память.

И последнее: вам не нужно ms.Dispose(); MemoryStream

Этот тип реализует IDisposable интерфейс, но на самом деле не имеет никаких ресурсов для удаления. Это означает, что удаление его с помощью прямого вызова Dispose () или использования языковой конструкции, такой как использование (в C#) или использование (в Visual Basi c), не требуется.

Так MemoryStream не будет проблемой.

...