My understanding is that return Task.FromResult(foo) is a simple
shorthand for... [TaskCompletionSource.SetResult
].
Actually, Task.FromResult
doesn't use TaskCompletionSource
, its implementation is much simpler than that.
Is there some equivalent for a task that returns an exception state?
I reckon TaskCompletionSource
would be the best option for this. You could also do something like this:
static Task FromExAsync(Exception ex)
{
var task = new Task(() => { throw ex; });
task.RunSynchronously();
return task;
}
The exception will not be propagated outside the returned task
, until observed via await task
or task.Wait()
, which should be a desired behavior.
Note that if the exception passed to FromExAsync
is an active exception (i.e. has been already thrown and caught elsewhere), re-throwing it like this would loose the current stack trace and Watson buckets information stored inside the exception. There are two ways of dealing with it:
- Wrap the exception with
AggregateException
. This will make the original exception available as AggregateException.InnerException
:
static Task FromExAsync(Exception ex)
{
var task = new Task(() => { throw new AggregateException(ex); });
task.RunSynchronously();
return task;
}
- Use
ExceptionDispatchInfo.Capture
to flow the active exception's state:
static Task FromExAsync(Exception ex)
{
var ei = System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex);
var task = new Task(() => { ei.Throw(); });
task.RunSynchronously();
return task;
}
Finally, perhaps the simplest yet the worst option (due to the overhead of the state machine and the compiler warning) is to throw from an async
method:
static async Task FromExAsync(Exception ex)
{
throw ex;
}