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

Blazor Server中如何通过BackgroundService触发UI更新

Blazor Server 实现BackgroundService数据更新后实时刷新UI

1. 创建数据更新通知服务

定义一个单例服务,作为BackgroundService和UI组件的消息传递桥梁:

public interface IDataUpdateNotificationService
{
    event Action OnDataUpdated;
    void NotifyDataUpdated();
}

public class DataUpdateNotificationService : IDataUpdateNotificationService
{
    public event Action OnDataUpdated;

    public void NotifyDataUpdated()
    {
        OnDataUpdated?.Invoke();
    }
}

在Program.cs中注册为单例:

builder.Services.AddSingleton<IDataUpdateNotificationService, DataUpdateNotificationService>();

2. 修改BackgroundService触发通知

在你的BackgroundService中注入通知服务,完成数据更新后触发事件:

public class YourBackgroundService : BackgroundService
{
    private readonly IDataUpdateNotificationService _notificationService;
    // 其他依赖(如数据访问服务)

    public YourBackgroundService(IDataUpdateNotificationService notificationService)
    {
        _notificationService = notificationService;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            // 执行API调用、数据转换、数据库更新逻辑
            await FetchAndUpdateData(stoppingToken);

            // 数据更新完成后发送通知
            _notificationService.NotifyDataUpdated();

            // 原有等待逻辑(例如下次更新间隔)
            await Task.Delay(TimeSpan.FromHours(1), stoppingToken);
        }
    }

    private async Task FetchAndUpdateData(CancellationToken stoppingToken)
    {
        // 你的数据更新实现
    }
}

3. UI组件订阅通知并刷新

在需要实时更新的组件中,注入通知服务,订阅事件并在触发时刷新UI,同时注意组件销毁时取消订阅避免内存泄漏:

@inject IDataUpdateNotificationService NotificationService
@implements IDisposable

<h3>实时数据展示</h3>

@foreach (var item in DataItems)
{
    <p>@item.Name: @item.Value</p>
}

@code {
    private List<YourDataModel> DataItems = new();
    private IDisposable? _subscription;

    protected override async Task OnInitializedAsync()
    {
        // 初始加载数据
        await LoadLatestData();

        // 订阅更新事件,必须通过InvokeAsync切换到UI线程
        _subscription = NotificationService.OnDataUpdated.Subscribe(async () =>
        {
            await InvokeAsync(async () =>
            {
                await LoadLatestData();
                StateHasChanged();
            });
        });
    }

    private async Task LoadLatestData()
    {
        // 从数据库加载最新数据
        DataItems = await YourDataAccessService.GetCurrentDataAsync();
    }

    public void Dispose()
    {
        // 取消订阅释放资源
        _subscription?.Dispose();
    }
}

关键注意事项

  • 线程安全:BackgroundService运行在后台线程,必须用InvokeAsync切换到UI线程再调用StateHasChanged,否则会抛出线程异常。
  • 内存泄漏:组件销毁时务必取消事件订阅,防止服务持有组件引用导致内存泄漏。
  • 性能优化:如果数据量较大,可改为增量更新(只同步变化的数据),减少数据库查询和UI渲染开销。
  • 异常处理:在事件回调中添加异常捕获,避免单个组件的异常影响其他订阅者。

增量更新替代方案

如果不需要全量刷新,可修改通知服务实现增量数据推送:

public interface IDataUpdateNotificationService
{
    IAsyncEnumerable<YourDataModel> GetIncrementalUpdatesAsync(CancellationToken cancellationToken);
    void PushUpdatedItem(YourDataModel item);
}

public class DataUpdateNotificationService : IDataUpdateNotificationService
{
    private readonly Subject<YourDataModel> _updateSubject = new();

    public IAsyncEnumerable<YourDataModel> GetIncrementalUpdatesAsync(CancellationToken cancellationToken)
    {
        return _updateSubject.AsAsyncEnumerable().WithCancellation(cancellationToken);
    }

    public void PushUpdatedItem(YourDataModel item)
    {
        _updateSubject.OnNext(item);
    }
}

组件中通过流式接收更新:

@code {
    protected override async Task OnInitializedAsync()
    {
        await foreach (var updatedItem in NotificationService.GetIncrementalUpdatesAsync(CancellationToken.None))
        {
            await InvokeAsync(() =>
            {
                var existing = DataItems.FirstOrDefault(x => x.Id == updatedItem.Id);
                if (existing != null)
                {
                    existing.Value = updatedItem.Value;
                }
                else
                {
                    DataItems.Add(updatedItem);
                }
                StateHasChanged();
            });
        }
    }
}

内容的提问来源于stack exchange,提问作者Jexodus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 05:22:19