是否有一种简单的方法可以返回带有异常的任务?

Mat*_*int 17 c# task-parallel-library async-await

我的理解是这return Task.FromResult(foo)是一个简单的简写:

var tcs = new TaskCompletionSource<TFoo>();
tcs.SetResult(foo);
return tcs.Task;
Run Code Online (Sandbox Code Playgroud)

是否有一些等效的任务返回异常状态?

var tcs = new TaskCompletionSource<TFoo>();
tcs.SetException(new NotSupportedException()); // or whatever is appropriate
return tcs.Task;
Run Code Online (Sandbox Code Playgroud)

我没有看到任何类似的东西Task.FromException.或者在不返回任务的情况下抛出异常会更合适吗?

Dre*_*kes 16

从.NET 4.6开始,Task.FromExceptionBCL中有一个方法.

还有Task.FromCanceled.


nos*_*tio 12

我的理解是返回Task.FromResult(foo)是... [ TaskCompletionSource.SetResult] 的简单简写.

实际上,Task.FromResult不使用TaskCompletionSource,它的实现比这简单得多.

是否有一些等效的任务返回异常状态?

我认为TaskCompletionSource这是最好的选择.你也可以这样做:

static Task FromExAsync(Exception ex) 
{
    var task = new Task(() => { throw ex; });
    task.RunSynchronously();
    return task;
}
Run Code Online (Sandbox Code Playgroud)

异常不会在返回之外传播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;
}
Run Code Online (Sandbox Code Playgroud)
  • 用于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;
}
Run Code Online (Sandbox Code Playgroud)

最后,也许最简单但最差的选项(由于状态机开销和编译器警告)是从一个async方法抛出:

static async Task FromExAsync(Exception ex)
{
    throw ex;
}
Run Code Online (Sandbox Code Playgroud)

  • @hvd,.NET 4.6中有新的`Task.FromException` API:http://blogs.msdn.com/b/pfxteam/archive/2015/02/02/new-task-apis-in-net-4- 6.aspx (5认同)
  • 也许值得注意的是,“Task”有一个内部“FromException”函数,并且它在内部使用与“TaskCompletionSource.TrySetException”完全相同的“Task.TrySetException”函数。这是我使用“TaskCompletionSource.TrySetException”的一个重要原因:您会得到 MS 认为“Task.FromException”的好主意的确切结果。 (2认同)