Blazor MAUI混合应用Base64图片内存泄漏原因咨询
Blazor MAUI (.NET 8) Base64图片展示内存泄漏问题分析
问题背景
使用.NET 8正式版开发Blazor MAUI混合应用,实现用户选择图片并展示功能时,采用Base64格式处理图片出现严重内存泄漏:每次上传图片后内存持续增长,GC无法回收多余内存,最终导致页面崩溃。
复现代码
初始实现的核心代码如下:
@page "/memory_leak" @using System.Diagnostics <MudStack Class="ma-4" AlignItems="AlignItems.Center"> <MudPaper Class="pa-3" Elevation="3"> @if (_imageBase64 is null) { <MudAlert Severity="Severity.Normal">Choose an Image</MudAlert> } else { <MudImage Height="400" Alt="pic" Class="rounded-lg" Src="@string.Concat("data:image/png;base64,", _imageBase64)" /> } </MudPaper> <MudFileUpload T="IBrowserFile" FilesChanged="UploadFiles" Class="pa-3"> <ButtonTemplate> <MudFab Size="Size.Small" HtmlTag="label" Color="Color.Secondary" Icon="@Icons.Material.Filled.Image" Label="Load picture" for="@context" /> </ButtonTemplate> </MudFileUpload> <MudPaper Class="pa-3">Item 3</MudPaper> </MudStack> @code { private string? _imageBase64; private async Task UploadFiles(IBrowserFile file) { Debug.WriteLine($"size:{file.Size}"); await using var openReadStream = file.OpenReadStream(file.Size); byte[] buffer = new byte[file.Size]; var readAsync = await openReadStream.ReadAsync(buffer); _imageBase64 = Convert.ToBase64String(buffer, 0, readAsync); } }
排查过程
- 注释掉
MudImage的Src绑定代码后,内存泄漏现象消失,确认泄漏与Base64图片展示逻辑直接相关。 - 替换为原生HTML
<img>标签后,问题依然存在,排除MudBlazor组件的影响:
@* <MudImage Height="400" Alt="pic" Class="rounded-lg" Src="@string.Concat("data:image/png;base64,", _imageBase64)" /> *@ <img src="@string.Concat("data:image/png;base64,", _imageBase64)" class="rounded-lg" height="400px"/>
解决方案
通过JavaScript Object URL机制解决了内存泄漏问题,核心思路是利用浏览器原生API管理图片资源,主动释放旧资源:
@page "/memory_leak" @inject IJSRuntime JS @implements IDisposable <MudStack Class="ma-4" AlignItems="AlignItems.Center"> <MudPaper Class="pa-3" Elevation="3"> @if (_imageUrl is null) { <MudAlert Severity="Severity.Normal">Choose an Image</MudAlert> } else { <img src="@_imageUrl" class="rounded-lg" height="400px"/> } </MudPaper> <MudFileUpload T="IBrowserFile" FilesChanged="UploadFiles" Class="pa-3"> <ButtonTemplate> <MudFab Size="Size.Small" HtmlTag="label" Color="Color.Secondary" Icon="@Icons.Material.Filled.Image" Label="Load picture" for="@context" /> </ButtonTemplate> </MudFileUpload> <MudPaper Class="pa-3">Item 3</MudPaper> </MudStack> @code { private string? _imageUrl; private string? _currentObjectUrl; private async Task UploadFiles(IBrowserFile file) { // 释放旧的Object URL if (!string.IsNullOrEmpty(_currentObjectUrl)) { await JS.InvokeVoidAsync("URL.revokeObjectURL", _currentObjectUrl); } // 创建新的Object URL _currentObjectUrl = await JS.InvokeAsync<string>("URL.createObjectURL", file); _imageUrl = _currentObjectUrl; StateHasChanged(); } public void Dispose() { // 组件销毁时释放资源 if (!string.IsNullOrEmpty(_currentObjectUrl)) { _ = JS.InvokeVoidAsync("URL.revokeObjectURL", _currentObjectUrl); } } }
问题根源分析
这并非代码用法错误,更可能是Blazor MAUI中WebView渲染引擎的内存管理问题:
- 当Base64字符串绑定到
<img>的src属性时,WebView底层渲染引擎(如Android WebView、iOS WKWebView)解析Base64为图片资源后,可能未正确释放对原始Base64字符串的引用; - Blazor更新
_imageBase64时,旧的Base64字符串因被WebView持有,无法被.NET GC回收,导致内存持续累积; - Object URL机制通过浏览器原生API管理资源,可主动调用
revokeObjectURL释放资源,从根源避免了引用泄漏。
内容的提问来源于stack exchange,提问作者fairjm
相关产品推荐
相关产品推荐

