为何未获取Task.Result时,Task的IsFaulted状态无法正确维持?
问题解析
你的问题核心在于**ContinueWith 任务如何处理前置任务的异常状态**,以及为什么访问 task.Result 会影响返回任务的 IsFaulted 属性。
关键原理:ContinueWith 的异常传播规则
当你调用 task.ContinueWith(delegate) 时,返回的是一个新的后续任务,其状态由以下规则决定:
- 如果前置任务(Firebase 登录任务)成功完成:后续任务的状态取决于委托代码是否正常执行——若委托未抛出异常,后续任务会标记为
RanToCompletion(成功完成)。 - 如果前置任务失败(
IsFaulted = true):- 若你在委托中未访问前置任务的
Result或主动抛出异常:委托仅执行日志打印等操作,不会触发异常。此时后续任务会被标记为RanToCompletion(成功完成),而非Faulted,无法反映前置任务的失败状态。 - 若你在委托中访问了
task.Result:由于前置任务已失败,访问Result会直接抛出导致前置任务失败的异常。该异常会被后续任务捕获,使其状态变为Faulted,从而保留原任务的失败状态。
- 若你在委托中未访问前置任务的
你的代码场景分析
- 省略
var result = task.Result;时:即使 Firebase 登录任务失败,委托仅打印错误日志,未抛出异常。返回的loginTask会被标记为成功完成(IsCompleted = true,IsFaulted = false),无法正确反映登录失败的实际情况。 - 保留
var result = task.Result;时:访问失败任务的Result会抛出异常,让后续任务(即loginTask)的状态变为Faulted,从而正确传递登录失败的状态。
更优雅的替代方案
直接访问 task.Result 虽能解决问题,但可读性较差。你可以主动抛出异常明确传播失败状态:
public Task SignInWithEmailAndPasswordAsync(string email, string password) { return auth.SignInWithEmailAndPasswordAsync(email, password).ContinueWith(task => { if (task.IsCanceled) { Debug.LogError("SignInWithEmailAndPasswordAsync was canceled."); throw new TaskCanceledException(task); } if (task.IsFaulted) { Debug.LogError("SignInWithEmailAndPasswordAsync encountered an error: " + task.Exception); throw task.Exception.Flatten(); } return task.Result; }); }
若环境支持 async/await,推荐使用更简洁的异步写法,它会自动处理异常传播:
public async Task SignInWithEmailAndPasswordAsync(string email, string password) { try { await auth.SignInWithEmailAndPasswordAsync(email, password); } catch (TaskCanceledException) { Debug.LogError("SignInWithEmailAndPasswordAsync was canceled."); throw; } catch (Exception ex) { Debug.LogError("SignInWithEmailAndPasswordAsync encountered an error: " + ex); throw; } }
内容的提问来源于stack exchange,提问作者rustyBucketBay
相关产品推荐
相关产品推荐

