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

Blazor 8(Server)状态管理:跨组件共享值与异步操作处理

解决方案:统一支持同步/异步回调的状态类实现

不需要定义两个状态事件,只需修正状态类的事件类型和触发逻辑,就能同时支持父组件的同步处理和Child2的异步操作。以下是正确的实现方式:

1. 修正状态类MyState

将事件类型改为Func<Task>?(支持异步回调),并修改SetSharedValue为异步方法,确保所有异步回调被正确等待:

public class MyState
{
    // 替换原有的Func<Action>,使用Func<Task>支持异步回调
    public event Func<Task>? StateChanged;
    public string SharedValue { get; private set; } = string.Empty;

    public async Task SetSharedValue(string value)
    {
        SharedValue = value;
        // 先获取当前所有订阅者,避免触发过程中订阅关系变更导致异常
        var handlers = StateChanged;
        if (handlers != null)
        {
            // 遍历每个订阅者并await,确保异步操作执行完成
            foreach (var handler in handlers.GetInvocationList().Cast<Func<Task>>())
            {
                await handler();
            }
        }
    }
}

2. Child1调用方式

由于SetSharedValue改为异步方法,调用时需要加await:

// Child1.razor.cs
await MyState.SetSharedValue("Hey");

3. Child2订阅异步回调并处理销毁

实现IDisposable接口,在组件销毁时取消订阅,防止内存泄漏:

// Child2.razor.cs
public class Child2 : ComponentBase, IDisposable
{
    [Inject] private MyState MyState { get; set; } = default!;
    // 假设第三方组件已注入或初始化
    private ThirdPartyComponent thirdPartyComponent = default!;

    protected override void OnInitialized()
    {
        MyState.StateChanged += HandleStateChangedAsync;
    }

    private async Task HandleStateChangedAsync()
    {
        // 执行第三方异步刷新方法
        await thirdPartyComponent.RefreshDataAsync();
        // 若需要更新组件UI,手动调用StateHasChanged
        StateHasChanged();
    }

    public void Dispose()
    {
        // 取消订阅事件
        MyState.StateChanged -= HandleStateChangedAsync;
    }
}

4. 父组件订阅实现

父组件无论是同步还是异步处理,都可以直接订阅同一个事件:

// Page.razor.cs
public class Page : ComponentBase, IDisposable
{
    [Inject] private MyState MyState { get; set; } = default!;

    protected override void OnInitialized()
    {
        MyState.StateChanged += ParentHandleStateChanged;
    }

    // 同步处理逻辑可使用async Task(或async void,推荐前者)
    private async Task ParentHandleStateChanged()
    {
        // 父组件的业务逻辑,比如更新本地状态、刷新UI
        StateHasChanged();
    }

    public void Dispose()
    {
        MyState.StateChanged -= ParentHandleStateChanged;
    }
}

关键说明

  • 原修改中使用Func<Action>是错误的,该类型代表返回Action的委托,而非异步委托,导致父组件无法正常订阅。正确的异步事件类型应为Func<Task>。
  • 触发事件时必须先获取当前订阅者列表,避免遍历过程中订阅关系变更引发异常。
  • 所有订阅事件的组件都需实现IDisposable,在销毁时取消订阅,防止内存泄漏。
  • 异步回调后若需更新UI,需手动调用StateHasChanged(),因为异步操作可能脱离Blazor的同步上下文。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 18:43:15