等待失败的任务时会发生什么

Sha*_*ade 6 .net c# asynchronous task-parallel-library async-await

我有一个理论问题.如果我等待另一个任务中的任务结果会怎样?我想知道我现在的系统是否会在之后运行.

任务启动并完成一些任务.在某些时候,该任务可能需要另一个任务,以便处理当前任务无法自行处理的数据.所以我使用await来确保当前任务不会继续,只要他没有辅助任务的结果.但是如果助手失败会发生什么?当前任务是否仍然锁定?

我可以以某种方式避免这种死锁(不改变系统本身 - 任务内部的任务)?

Ste*_*ary 6

任务启动并完成一些任务.在某些时候,该任务可能需要另一个任务,以便处理当前任务无法自行处理的数据.所以我使用await来确保当前任务不会继续,只要他没有辅助任务的结果.但是如果助手失败会发生什么?当前任务是否仍然锁定?

背后的核心思想是异步代码asyncawait同步代码的工作方式大致相同.

所以,如果你有这样的同步代码:

void HelperMethod()
{
  throw new InvalidOperationException("test");
}

void DoStuff()
{
  HelperMethod();
}
Run Code Online (Sandbox Code Playgroud)

那么你期望从辅助方法DoStuff传播InvalidOperationException.同样,这就是异步代码所发生的情况:

async Task HelperMethodAsync()
{
    throw new InvalidOperationException("test");
}

async Task DoStuffAsync()
{
    await HelperMethodAsync();
}
Run Code Online (Sandbox Code Playgroud)

也就是说,DoStuffAsync也将传播InvalidOperationException.

现在,它不会以完全相同的方式工作,当然,因为它必须是异步的,但一般的想法是所有的控制流,如try/ catch,for循环等,所有"只是工作"异步代码非常类似于同步代码.

什么是真正回事的是,当HelperMethod与结束InvalidOperationException,异常被捕获并放置在返回Task,并且任务完成.当awaitin DoStuffAsync看到任务已完成时,它会检查其异常并重新引发第一个(在这种情况下,只有一个,InvalidOperationException).它以一种在异常上保留调用堆栈的方式重新引发它.这反过来导致Task返回的from DoStuffAsync完成同样的异常.

因此,在幕后async并且await正在做一些工作以确保您可以使用await和使用try/ catch以同步代码中相同的方式调用其他方法.但大多数时候你不必知道这一点.