Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/83.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# Blazor服务器端项目中的内存泄漏_C#_Asp.net_Entity Framework_Blazor Server Side - Fatal编程技术网

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

C# Blazor服务器端项目中的内存泄漏,c#,asp.net,entity-framework,blazor-server-side,C#,Asp.net,Entity Framework,Blazor Server Side,我制作了一个简单的系统,可以从EF Core数据库中添加和删除文件,如下所示: 添加一个文件: public async Task AddFile(IFileListEntry file) { File fileToAdd = await File.GetFileAsync(file); _context.Files.Add(fileToAdd); _context.SaveChanges(); } 从IFileListEntry界面获取文件,将文件包含在流中: p

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

  • 添加一个文件:

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

    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;
    }
    
所有添加的文件都存储在
列表中
,并从中删除,列表本身包含在
.razor
文件中(此处未显示,因为我认为这与我的问题无关),也包含在EF核心数据库中

数据库上下文
\u context
通过依赖注入获得,并从
DbContext
类继承


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


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

我认为您的DI容器没有处理dbcontext

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

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

因此,如果您的DI没有处理上下文,那么它将保留在内存中,因此,看起来您有泄漏

另一件可能发生的事情是,垃圾收集不会以可预测的方式发生。因此,可能需要一些时间才能看到释放的内存

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

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


因此,
MemoryStream
不会成为问题。

“添加和删除文件后,我可以观察到内存泄漏,因为在将文件添加到数据库和列表后,RAM处于相同的级别。”这听起来不像内存泄漏。这就是.NET内存堆的工作原理。我并没有指出Blazor或ASP.NET框架的内存泄漏。当然,我只是想弄清楚这个未使用的、可能是无用的分配内存被保存在哪个变量中,以及如何处理它,因为在上传一个映像后,有时可能需要100MB的RAM,因此,一些东西可能会很快导致RAM被数百次上传完全填满@athanasios kataras确实回答了我的问题,我将尝试手动处理上下文以清除这些未使用的内存。感谢您的回答,它似乎符合逻辑,因为它来自未被处理的
DbContext
。我真的不明白为什么DI不处理它。因此,解决方案是手动处理它,还是使用
using
语句?知道我是通过DI获得这个上下文的,我如何应用其中一个解决方案呢?(很抱歉回答晚了,我刚在下班前发布了此消息)取决于DI。例如,在netcore中,AddDbContext扩展方法默认使用作用域生存期注册DbContext类型。因此,默认情况下处理处置。这取决于您正在使用的DI实现。我的DI实现是您在创建简单的Blazor服务器端项目和标识脚手架后获得的,因此上下文注入在脚手架
IdentityHostingStartupClass:IHostingStartup
类中处理,如下所示:
builder.ConfigureServices((context,services)=>{services.AddDbContext(options=>options.UseSqlServer(context.Configuration.GetConnectionString(“…”))
经过更多的测试,我发现了非常奇怪的事实:在一定数量的上传之后,GC似乎完成了他的工作,RAM稳定在大约400MB的值,尽管我仍然不明白为什么。同样的,如果你点击导航栏标签,RAM会不断增加,直到GC收集到一个点,然后RAM保持稳定。我真的不明白下面的“魔力”,但至少它似乎可以通过“自身”避免内存泄漏。再次感谢您的帮助。干杯!似乎这是一些GC魔力。您用于DI的方法正确地处理了上下文,所以您应该没事!
public void DeleteFile(File file)
{
    file.Data = new byte[0]; //Test
    _context.Files.Remove(file);
    _context.SaveChanges();
}
public void UseProducts()
{
    using (var context = new ProductContext())
    {     
        // Perform data access using the context
    }
}