如何防范Blazor wasm中异步方法的双重触发

How to guard against double trigger of async method in Blazor wasm

我正在开发一个 blazor wasm 应用程序。我正在努力解决异步问题 - 我发现很难解决,因为浏览器中的线程对我来说并不完全清楚。我没有使用任何异步空隙 - 一切都是异步任务。

从 API 调用(异步)我得到了两个对象。一个对象作为同步更新分派到 fluxor store,另一个我必须在本地 Indexdb 上进行异步调用,之后这个对象也进入 fluxor store。

这两个 fluxor store updates 通过事件触发 view model 的更新方法。此更新方法是异步的,因为它还从 IndexedDb 获取一些信息。此异步方法从 Indexdb 异步获取一些项目,清除字典,然后枚举 属性 的 fluxor 存储以更新模型。

此方法被快速连续调用两次,结果开始交织。

问题是第一个方法调用在状态枚举期间暂停,接下来第二个方法调用清除字典,并开始它自己的枚举(并完成),之后第一个方法在它更早开始的时候恢复枚举。

这会导致错误 - 尝试将相同的键添加到字典中两次。

如何防范? 如何防止相同的方法调用在 Blazor wasm 中与自身交织? 如何暂停异步更新方法的(同步)枚举部分,允许完整方法 运行,然后再次恢复第一次调用?

public partial class DebugPage : BasePage, IDisposable
{


    [Inject] IState<MonthBalanceState> MonthBalanceState { get; set; }

    private Dictionary<IMonthBalanceAddress, int> DbCountDictionary = new Dictionary<IMonthBalanceAddress, int>();

    protected override async Task OnParametersSetAsync()
    {
        MonthBalanceState.StateChanged += async (_, _) => await MonthBalanceState_StateChanged();
        Console.WriteLine($"Linkage made to Monthbalance State");
        await base.OnParametersSetAsync();
    }

//This method get's called twice quickly - starting the interweaving
    private async Task MonthBalanceState_StateChanged()
    {
        Console.WriteLine($"Update via Statechanged Monthbalance State");
        var result = await UpdateDictionaryAsync();
    }
    private async Task<bool> UpdateDictionaryAsync()
    {
        DbCountDictionary.Clear();
        Log.Debug("Debug dictionary updated");
        foreach (IMonthBalanceLoadable mb in MonthBalanceState.Value.MonthBalances.ToList())
        {
            Console.WriteLine($"Adding {mb.Address.ToString()}");
            DbCountDictionary.Add(mb.Address, await Db.GetCountByAddress(mb.Address));
        }
        return true;
    }

如果可能,您可以使用 OnAfterRenderAsync(bool firstRender) 而不是 OnParametersSetAsync(),然后仅在它是第一个渲染时才设置变量。

    += async (_, _) => await MonthBalanceState_StateChanged();

此 lambda 是 async void 包装您的处理程序。

所以没有等待整体,这就是问题的根源。

StateChanged 事件可能应该是一个 EventCallback 属性。 Post 如果您需要更多帮助,请查看相关代码。