我的理解是return Task.FromResult(foo)
是一个简单的简写:
var tcs = new TaskCompletionSource<TFoo>();
tcs.SetResult(foo);
return tcs.Task;
是否有一些等同于返回异常状态的任务?
var tcs = new TaskCompletionSource<TFoo>();
tcs.SetException(new NotSupportedException()); // or whatever is appropriate
return tcs.Task;
我看不到Task.FromException
之类的内容。或者在不返回任务的情况下抛出异常会更合适吗?
答案 0 :(得分:14)
从.NET 4.6开始,BCL中有一个Task.FromException
方法。
答案 1 :(得分:12)
我的理解是返回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;
}