Blazor Server调用StateHasChanged()后摄像头图片仍不更新求助
Blazor Server摄像头图像不更新问题修复
问题排查方向
你的Base64图像有效但页面不更新,主要可能出在渲染触发逻辑、资源释放或回调上下文这几个点:
- 自定义的
ShouldRender逻辑可能意外阻止了渲染; - 回调中未正确释放
Bitmap和MemoryStream,导致内存泄漏或图像数据异常; - FlashCap的回调线程上下文与Blazor同步上下文不匹配,
InvokeAsync的执行时机有问题。
分步修复方案
1. 移除不必要的ShouldRender限制
Blazor Server中调用InvokeAsync(StateHasChanged)本身就会触发组件重新渲染,自定义ShouldRender的条件反而可能抑制正常渲染。先去掉这部分代码:
@page "/" <PageTitle>Index</PageTitle> <div style="width: 100%; height: 500px;border: solid green 1px"> <img src="@ImageSource" style="height: 100%; width: 100%; margin: auto; border: solid red 1px;" /> </div> @code { public string? ImageSource { get; set; } protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); Console.WriteLine("init"); Webcam.Instance?.Init(async bufferScope => { byte[] image = bufferScope.Buffer.ExtractImage(); // 使用using自动释放资源,避免内存泄漏 using var ms = new MemoryStream(image); using var bmp = Bitmap.FromStream(ms); ImageSource = ToBase64Image(bmp); await InvokeAsync(StateHasChanged); Console.WriteLine("running again"); }, true); } public static string ToBase64Image(Image bmp) { using var stream = new MemoryStream(); bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Png); return "data:image/png;base64," + Convert.ToBase64String(stream.ToArray()); } }
2. 修复Webcam类的异步方法调用
原Webcam类的Start和Stop方法调用异步方法却未等待,可能导致摄像头启动/停止逻辑异常:
using FlashCap; namespace CameraServer.Data { public class Webcam { public static Webcam? Instance { get; private set; } private CaptureDeviceDescriptor DeviceDescriptor { get; set; } public CaptureDevice Device { get; private set; } public Webcam(CaptureDeviceDescriptor deviceDescriptor) { DeviceDescriptor = deviceDescriptor; Instance = this; } public async Task<Webcam?> Init(PixelBufferArrivedDelegate func, bool start = false) { Device = await DeviceDescriptor.OpenAsync(DeviceDescriptor.Characteristics[0], func); if (start) await Device.StartAsync(); return Instance; } // 改为异步方法并等待 public async Task Start() => await Device?.StartAsync()!; public async Task Stop() => await Device?.StopAsync()!; } }
3. 可选:绕过浏览器缓存
如果浏览器缓存了初始图像,即使src更新也不刷新,可以给Base64 URL添加随机参数:
ImageSource = $"data:image/png;base64,{Convert.ToBase64String(stream.ToArray())}?t={DateTime.Now.Ticks}";
验证方法
- 启动应用后,查看控制台是否持续输出"running again",确认回调在正常触发;
- 打开浏览器开发者工具,检查
<img>标签的src属性是否持续变化; - 若
src变化但图像未更新,添加上述随机参数验证是否为缓存问题。
内容的提问来源于stack exchange,提问作者juffma
相关产品推荐
相关产品推荐

