我的理解是,返回Task.FromResult(foo)是一個簡單的 ... [TaskCompletionSource.SetResult
]的簡寫。
其實,Task.FromResult
不使用TaskCompletionSource
,its implementation比簡單得多。
對於返回異常狀態的任務是否存在一些等價物?
我估計TaskCompletionSource
將是最好的選擇。你也可以做這樣的事情:
static Task FromExAsync(Exception ex)
{
var task = new Task(() => { throw ex; });
task.RunSynchronously();
return task;
}
的異常不會返回task
外面傳播,直到通過await task
或task.Wait()
,這應該是一個期望的行爲觀察。
請注意,如果傳遞給FromExAsync
的異常是活動異常(即已被拋出並被捕獲到其他地方),那麼重新拋出它會丟失當前堆棧跟蹤和Watson存儲區異常中存儲的信息。有兩種處理方式:
- 用
AggregateException
包裝例外。這將提供原始異常爲AggregateException.InnerException
:
static Task FromExAsync(Exception ex)
{
var task = new Task(() => { throw new AggregateException(ex); });
task.RunSynchronously();
return task;
}
- 使用
ExceptionDispatchInfo.Capture
流活動異常的狀態:
static Task FromExAsync(Exception ex)
{
var ei = System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex);
var task = new Task(() => { ei.Throw(); });
task.RunSynchronously();
return task;
}
最後,也許最簡單但最糟糕的選擇(由於overhead of the state machine和編譯器警告)是從async
方法拋出:
static async Task FromExAsync(Exception ex)
{
throw ex;
}
看着你的代碼讓我想要選擇它並在ReSharper中使用「提取方法」。 –
看來,這種方法是故意不暴露的:它存在,但是「內部」。 – dlev
該方法的問題在於,您返回的異常不會有堆棧跟蹤,因爲它實際上不會被拋出。也許這就是爲什麼FromException沒有公開。 –