You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 04:39:52