Blazorise Charts加载数据库数据时重绘前数据为空问题求助
解决Blazorise Charts数据加载后重绘为空的问题
问题原因分析
你的代码逻辑中,OnInitializedAsync虽同步等待了所有数据加载和处理操作,但存在几个导致OnAfterRenderAsync首次重绘时数据为空的问题:
ConfigureAwait(false)的使用可能导致数据赋值脱离组件UI上下文,组件未感知到数据更新- 依赖
firstRender触发重绘的时机,和数据最终处理完成的时序不匹配 UpdateDatasetCountByNameAsync中不必要的Task.Run导致数据在后台线程赋值,组件未及时获取最新数据- 未显式触发组件状态更新,数据加载完成后组件未重新渲染
解决方案
1. 移除不必要的Task.Run并简化数据处理
UpdateDatasetCountByNameAsync中的LINQ查询属于轻量CPU操作,无需用Task.Run包装,直接同步执行避免线程上下文问题:
private void UpdateDatasetCountByName() { if (stateContainer.Version == "All") { eventNameCountByName = eventNameCountByNameData .GroupBy(x => x.Key, (key, group) => new ItemCount<string>(key, group.Sum(x => x.Count))) .ToList(); } else { eventNameCountByName = eventNameCountByNameData .Where(x => x.Version.StartsWith(stateContainer.Version)) .GroupBy(x => x.Key, (key, group) => new ItemCount<string>(key, group.Sum(x => x.Count))) .ToList(); } }
2. 数据加载完成后显式触发状态更新
在OnInitializedAsync末尾调用StateHasChanged(),确保组件感知到数据变化:
protected override async Task OnInitializedAsync() { stateContainer.PropertyChanged += StateContainer_PropertyChanged; using var dbHelper = new TelemetryDataHelper(dbContextFactory.CreateDbContext(), appCache); eventNameCountByNameData = await dbHelper.GetEventNameCountByNameAsync(); eventNameCountByVersionData = await dbHelper.GetEventNameCountByVersionAsync(); UpdateDatasetCountByName(); // 直接调用同步方法 //Extract primary Versions eventNameCountByVersion = eventNameCountByVersionData .Select(x => new ItemCount<string>(x.Key.Substring(0, x.Key.IndexOf('.', x.Key.IndexOf('.') + 1)), x.Count)) .GroupBy(x => x.Key, (key, group) => new ItemCount<string>(key, group.Sum(x => x.Count))) .ToList(); await AddPercentageToCountByVersionAsync(); isLoading = false; StateHasChanged(); // 显式通知组件更新状态 }
3. 调整重绘触发逻辑,不再依赖firstRender
将重绘逻辑改为判断数据是否就绪,而非仅依赖首次渲染:
protected override async Task OnAfterRenderAsync(bool firstRender) { await base.OnAfterRenderAsync(firstRender); // 数据加载完成且未重绘过时触发 if (!isLoading && !_hasRenderedCharts) { await HandleRedrawCountByNameAsync(); await HandleRedrawCountByVersionAsync(); _hasRenderedCharts = true; } } // 新增字段标记图表是否已重绘 private bool _hasRenderedCharts;
4. 处理stateContainer版本变化场景
在状态容器的属性变更事件中,同步更新数据集并重绘图表:
private void StateContainer_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(stateContainer.Version)) { UpdateDatasetCountByName(); // 触发组件更新并重新绘制图表 InvokeAsync(async () => { await HandleRedrawCountByNameAsync(); StateHasChanged(); }); } }
关键注意事项
- Blazor组件中避免滥用
ConfigureAwait(false),涉及状态更新的代码块使用该配置可能导致UI上下文丢失 - 图表重绘必须确保数据完全就绪,依赖
firstRender的方式无法保证异步数据加载的时序 - 依赖外部状态容器的数据时,需在状态变化时同步更新本地数据集并触发重绘
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

