C# 在Linq表达式中使用Async/Await不会引发异常

C# 在Linq表达式中使用Async/Await不会引发异常,c#,linq,exception,async-await,C#,Linq,Exception,Async Await,晚上, 有人能告诉我为什么使用async和await运算符的linq语句不会向堆栈上传播异常,而foreach循环会传播异常?一定有什么东西在引擎盖下,并记录在某个地方的这种行为,我只是没有运气找到它#googlefoofail#doyouevenasyncbrah 如果运行单元测试,您将看到它返回时没有错误且有效。但是,如果调试单元测试,它将在出现错误时中断,但是它将允许您继续,并且该错误不会传播到堆栈中 如果注释掉linq语句并取消对foreach循环的注释,则在尝试向字典添加重复键时会出现

晚上,

有人能告诉我为什么使用async和await运算符的linq语句不会向堆栈上传播异常,而foreach循环会传播异常?一定有什么东西在引擎盖下,并记录在某个地方的这种行为,我只是没有运气找到它#googlefoofail#doyouevenasyncbrah

如果运行单元测试,您将看到它返回时没有错误且有效。但是,如果调试单元测试,它将在出现错误时中断,但是它将允许您继续,并且该错误不会传播到堆栈中

如果注释掉linq语句并取消对foreach循环的注释,则在尝试向字典添加重复键时会出现预期的错误

[TestMethod]
公共空间测试器()
{
列表对=新列表()
{ 
{new KeyValuePair(“test”,“first”)},
{新的KeyValuePair(“test”,“second”)}
};
失败=新建字典();
ForEach(异步x=>await-testasync(x))//
有人能告诉我为什么使用async和await运算符的linq语句不会向堆栈上传播异常,而foreach循环会传播异常

实际上,它不是LINQ语句;它是
List.ForEach
List.ForEach
不与
async
lambdas一起工作,因为它只需要
void
-返回委托类型,而不是
任务
-返回委托类型。因此
async
lambda成为
async void
方法

有人能告诉我为什么使用async和await运算符的linq语句不会向堆栈上传播异常,而foreach循环会传播异常

实际上,它不是LINQ语句;它是
列表。ForEach
列表。ForEach
不与
async
lambdas一起工作,因为它只需要
void
返回委托类型,而不是
任务
返回委托类型。因此
async
lambda成为
async void
方法,这就是。

用来解释的n您看到的行为。关键摘录:

当异步运行的任务引发异常时,该任务将出错。任务对象保存在task.exception属性中引发的异常。出现故障的任务在等待时引发异常

由于您从未等待Lambda的结果,因此从未引发结果任务中存储的异常。您可以执行以下任一操作来修复该问题:

    // more equivalent to your `foreach` loop.
    pairs.ForEach(x => testasync(x).GetAwaiter().GetResult());
    Task.WhenAll(pairs.Select(async x => await testasync(x))).GetAwaiter().GetResult();
    // preferred
    await Task.WhenAll(pairs.Select(async x => await testasync(x)));
最后一行是最好的方法,但是为了使用
await
,您必须使调用方法
异步,这意味着您应该将其更改为返回一个
任务
,调用它的任何人都应该
await
返回的
任务
,等等,直到整个调用链为止。这就是人们在嘿,说“一路异步”来解释你看到的行为。关键摘录:

当异步运行的任务引发异常时,该任务将出错。任务对象保存在task.exception属性中引发的异常。出现故障的任务在等待时引发异常

由于您从未等待Lambda的结果,因此从未引发结果任务中存储的异常。您可以执行以下任一操作来修复该问题:

    // more equivalent to your `foreach` loop.
    pairs.ForEach(x => testasync(x).GetAwaiter().GetResult());
    Task.WhenAll(pairs.Select(async x => await testasync(x))).GetAwaiter().GetResult();
    // preferred
    await Task.WhenAll(pairs.Select(async x => await testasync(x)));

最后一行是最好的方法,但是为了使用
await
,您必须使调用方法
异步,这意味着您应该将其更改为返回一个
任务
,调用它的任何人都应该
await
返回的
任务
,等等,直到整个调用链为止。这就是人们在嘿,说“一路异步”。

不确定文档,但这里提到的扩展方法可能会帮助您引发异常。不确定文档,但这里提到的扩展方法可能会帮助您引发异常。