C# 如何正确地重新引发已处于故障状态的任务的异常?

C# 如何正确地重新引发已处于故障状态的任务的异常?,c#,.net,task-parallel-library,async-await,C#,.net,Task Parallel Library,Async Await,我有一个同步方法,其中包括检查挂起任务的状态,并重试其异常(如果有): void Test(Task task) { // ... if (task.IsFaulted) throw task.Exception; // ... } 这不会传播异常堆栈跟踪信息,并且对调试器不友好 现在,如果测试是异步的,它就不会像这样简单和自然了: async Task Test(Task task) { // ... if (task.IsFaulte

我有一个同步方法,其中包括检查挂起任务的状态,并重试其异常(如果有):

void Test(Task task)
{
    // ...
    if (task.IsFaulted)
        throw task.Exception;
    // ...
}
这不会传播异常堆栈跟踪信息,并且对调试器不友好

现在,如果
测试
异步的
,它就不会像这样简单和自然了:

async Task Test(Task task)
{
    // ...
    if (task.IsFaulted)
        await task; // rethrow immediately and correctly
    // ...
}
问题:如何为同步方法做好准备?我已经想到了这一点,但我不喜欢它:

void Test(Task task)
{
    // ...
    if (task.IsFaulted)
        new Action(async () => await task)();
    // ...
}

要正确地重新引发异常,应使用
ExceptionDispatchInfo

ExceptionDispatchInfo.Capture(task.Exception.InnerException).Throw();
您还可以执行以下操作:


另外,您的
操作
方法将无法正常工作,因为您正在创建一个
异步void
方法,并且无法捕获从该方法传播的异常。

可能尝试访问任务。结果?@Strilanc,这是一个非通用的
任务
任务,因此它没有
结果
。感谢@StephenCleary提供全面的答案,我学到了有关
异步void
的新知识。我认为,由于
task
已经处于完成状态,因此
新操作(async()=>await task)(
lambda将同步执行,从而引发调用线程的同步上下文。事实上,它是同步执行的,但异常不会传播到调用上下文中。我刚刚意识到,我还可以使用
task.Wait()
在非异步方法中重新执行,即
if(task.IsFaulted)task.Wait()。不过,我确实得到了
AggregatedException
。这有意义吗?@avo:是的,有意义
Wait
任务
类型从其原始设计中保留下来的,它是并行任务库的一部分。因此,
Wait
(和
Result
)将1)在必要时阻塞线程,2)在
aggregateeexception
中包装任何错误。这是意料之中的,这就是为什么我的示例代码实际抛出
InnerException
task.GetAwaiter().GetResult();