Blazor Server异步任务调用引发父任务重复执行问题求助
Blazor Server中LoadDataForScheduler因Graph API异步调用重复执行的解决方案
可能的原因
Blazor Server的组件渲染依赖状态变更触发重渲染,异步操作完成后会自动调用StateHasChanged。如果LoadDataForScheduler的触发逻辑(比如绑定到生命周期方法、UI回调)与状态变更形成循环,就会导致重复执行。此外,Graph API调用过程中若意外修改了组件绑定的参数(如用户邮箱),也会触发组件重渲染并再次调用该方法。
解决方案
1. 添加防重复执行标记
在组件中维护一个加载状态标记,执行LoadDataForScheduler前检查是否正在加载,避免重复触发:
private bool _isLoading = false; public async Task LoadDataForScheduler(SchedulerArgs args) { if (_isLoading) return; try { _isLoading = true; // 调用Graph API获取数据 List<Appointment> outlookAppointments = await _graphController.GetAllEventsForUser(userEmail, args.Start, args.End); // 更新调度器数据逻辑 } finally { _isLoading = false; } }
2. 排查触发时机与生命周期绑定
- 确认
LoadDataForScheduler是否绑定在OnParametersSetAsync这类生命周期方法中,若用户选择变更导致参数重复更新,会反复触发该方法。可通过对比参数变更前后的值,仅在实际变化时执行加载:private string _previousUserEmail; protected override async Task OnParametersSetAsync() { if (_previousUserEmail != userEmail) { _previousUserEmail = userEmail; await LoadDataForScheduler(currentSchedulerArgs); } } - 检查调度器组件的事件绑定(如
DataBinding)是否被重复注册,导致回调多次触发。
3. 使用CancellationToken取消重复请求
维护一个CancellationTokenSource,每次触发加载时取消之前未完成的请求,避免重复执行:
private CancellationTokenSource _loadCts; public async Task LoadDataForScheduler(SchedulerArgs args) { // 取消之前的请求 _loadCts?.Cancel(); _loadCts?.Dispose(); _loadCts = new CancellationTokenSource(); try { // 将令牌传入Graph API调用 List<Appointment> outlookAppointments = await _graphController.GetAllEventsForUser(userEmail, args.Start, args.End, _loadCts.Token); // 更新调度器数据 } catch (OperationCanceledException) { // 忽略已取消的请求 } finally { _loadCts.Dispose(); _loadCts = null; } }
同时修改GetAllEventsForUser方法,传入取消令牌:
public async Task<List<Appointment>> GetAllEventsForUser(string email, DateTime start, DateTime end, CancellationToken cancellationToken = default) { var response = await _graphServiceClient.Users[email].Events.GetAsync((requestConfiguration) => { requestConfiguration.QueryParameters.Expand = new string[] { "singleValueExtendedProperties($filter=id eq 'String {00020329-0000-0000-C000-000000000046} Name proplanid')" }; requestConfiguration.QueryParameters.Filter = $"start/dateTime ge '{start:o}' and end/dateTime le '{end:o}'"; requestConfiguration.QueryParameters.Top = 99; requestConfiguration.Options.WithAppOnly(); requestConfiguration.Options.ToDynamicList(); }, cancellationToken); // 转换为Appointment列表并返回 }
4. 检查状态变更源
排查GetAllEventsForUser方法或Graph API响应处理逻辑中,是否意外修改了组件绑定的参数(如userEmail)或其他触发重渲染的状态,导致组件反复刷新并调用加载方法。
内容的提问来源于stack exchange,提问作者Nunile
相关产品推荐
相关产品推荐

