C#中async/await竞态条件问题:如何确保先获取再保存数据
C# async/await 竞态条件解决思路
问题根源
你的代码里竞态条件的核心问题是**async void的滥用**:
OnRefresh是async void方法,调用它时无法通过await等待其异步操作完成Dispatcher.InvokeAsync传入的是async void委托,await这个InvokeAsync只能等待委托开始执行,而委托内部的await Task.Delay和OnRefresh会被“火并遗忘”,导致后续的OnSaveTrades提前执行
修复步骤
将
OnRefresh改为返回Task的异步方法
把async void换成async Task,让调用方可以等待其完成:private async Task OnRefreshAsync() { try { var trades = await ExchangeServiceInstance.GetTrades(""); mmTrades = new ObservableCollection<EEtrade>(trades); tradeListView.ItemsSource = mmTrades; } catch { } }修改
Dispatcher.InvokeAsync的委托类型
使用Func<Task>代替Action,并在委托内部await新的OnRefreshAsync,确保所有异步逻辑执行完毕后再继续:public async void OnSignalReceived() { // 现在会等待内部所有异步操作完成后再往下走 await tradeListView.Dispatcher.InvokeAsync(async () => { if (ExchangeServiceInstance.SelectedTabIndex == CURRENT_TAB_INDEX_ITEM) { await Task.Delay(MMConfig.DELAYMILLISEC); await OnRefreshAsync(); // 等待刷新操作完全完成 } }); // 此时mmTrades已经被正确赋值,可安全执行保存 await OnSaveTrades(); }
关键说明
async void仅适合UI事件处理器这类必须无返回值的场景,其他需要等待的异步逻辑必须用async Task/async Task<T>,这样才能通过await构建可靠的异步调用链Dispatcher.InvokeAsync接受Func<Task>时,返回的Task会包含委托内部所有异步操作的完成信号,await它就能确保整个Dispatcher逻辑执行完毕
内容的提问来源于stack exchange,提问作者Zaken
相关产品推荐
相关产品推荐

