移动端APP同步时触发Logout崩溃的优雅修复方案咨询
移动端APP同步期间触发登出导致崩溃问题
问题背景
- Sync(同步):同步应用的整体状态与输出信息
- Logout(登出):执行后会清除所有数据与服务
当同步操作(耗时约2秒)进行时点击Logout,APP会崩溃。原因是线程仍会进入while循环并访问UpdateFrequencyInSeconds字段,此时该字段所属的服务已被登出操作清除,进而引发异常。
原有代码
private async void ThreadSync(CancellationToken token) { while (token.IsCancellationRequested is false) { await Sync().ConfigureAwait(false); await Task.Delay(organizationAppSettingsService.UpdateFrequencyInSeconds * 1000).ConfigureAwait(false); } }
已实现的可行方案(不够简洁优雅)
方案一:
private async void ThreadSync(CancellationToken token) { while (token.IsCancellationRequested is false) { var updateFrequencyInSeconds = organizationAppSettingsService.UpdateFrequencyInSeconds * 1000; await Sync().ConfigureAwait(false); await Task.Delay(updateFrequencyInSeconds).ConfigureAwait(false); } }
方案二:
private async void ThreadSync(CancellationToken token) { while (token.IsCancellationRequested is false) { await Sync().ConfigureAwait(false); if (token.IsCancellationRequested is false) await Task.Delay(organizationAppSettingsService.UpdateFrequencyInSeconds * 1000).ConfigureAwait(false); } }
无效尝试
曾尝试传入token到Task.Delay:
await Task.Delay(organizationAppSettingsService.UpdateFrequencyInSeconds * 1000, token).ConfigureAwait(false);
但该方式会先获取UpdateFrequencyInSeconds字段值,再检查token状态,无法避免崩溃。
需求
寻求简洁优雅的解决方案,确保在token已取消时不会访问UpdateFrequencyInSeconds字段。
附Sync方法代码
public async Task Sync() { if (networkManager.IsNetworkAvailable is false || IsSyncInProgress || (DateTime.Now - _lastSyncedTime).TotalSeconds < organizationAppSettingsService.UpdateFrequencyInSeconds) return; IsSyncInProgress = true; _logger.LogInformation($"[BackgroundSync] Updating"); var waiting = Task.Delay(2000); ShowSyncProgress?.Invoke(); try { UpdateLocation(); await ordersRepository.UpdateOrders(_courierLocations, _ordersDtos).ConfigureAwait(false); var updateServiceInfo = !_lastServiceInfoUpdated.HasValue || (DateTime.Now - _lastServiceInfoUpdated.Value).TotalSeconds >= IAppSettingsService.DefaultServiceRequestFrequency; if (updateServiceInfo) { await UpdatePaymentTypes().ConfigureAwait(false); _lastServiceInfoUpdated = DateTime.Now; } Synced = true; _courierLocations.Clear(); var orders = Orders?.Where(x => (DateTime.Now - x.DeliveryDate).TotalHours < 24).ToList(); if (orders is null || orders.Any() is false) { SyncCompleted?.Invoke(); return; } await waiting; SyncCompleted?.Invoke(); } catch (SessionExpiredException) { await RecoverTransportSession().ConfigureAwait(false); } catch (Exception ex) { CatchSyncException(ex); } finally { _lastSyncedTime = DateTime.Now; IsSyncInProgress = false; HideSyncProgress?.Invoke(); _logger.LogInformation("[BackgroundSync] Update completed"); } }
内容的提问来源于stack exchange,提问作者rinyasuper
相关产品推荐
相关产品推荐

