[英]C# Async Exception Wrapping
我一直在使用.NET 4.6.1中的异步调用,我想知道抛出错误的正确方法是来自需要异步方法但实际上是同步的接口的实现者。 例如:
public interface ISomeInterface
{
Task ExecuteAsync();
}
public class SomeClass : ISomeInterface
{
public Task ExecuteAsync()
{
return Task.FromException(new Exception());
}
}
我在这里找到了Task.FromException
。
所以这是.NET 4.6仍然似乎建议包装异常。 但是我可以写下面的代码:
public class SomeClass : ISomeInterface
{
public Task ExecuteAsync()
{
throw new Exception();
}
}
当我使用try / catch块调用第二个实现时,客户端捕获了Exception
,我认为这就是为什么我们首先使用Task.FromException
,而且它还包含原始异常的整个调用堆栈(而方法一只有一个堆栈跟踪到等待客户端的操作)。 那时似乎第二种方法更好,但似乎每个人都使用方法一。 由于async
的实现发生了变化,现在是方法之一已经过时了,还是我缺少什么?
我还注意到在堆栈跟踪中, async
方法现在不会在调用之间引入任何额外的帧。 我假设这只是为了简化读取堆栈跟踪?
抛出错误的正确方法是来自需要异步方法但实际上是同步的接口的实现者。
如您所发现的,您可以直接抛出异常,也可以将异常放在返回的Task
。
请注意,这会在观察到异常的地方发生变化:
var task = obj1.ExecuteAsync();
await task;
如果直接抛出异常,则会在调用ExecuteAsync
抛出异常。 如果在返回的任务上放置了异常,则在await
任务时抛出该异常。 大多数情况下,任务在调用方法后立即await
,但并非总是如此(例如,在Task.WhenAll
各种场景中)。
使用异步(任务返回)API,返回的任务表示方法的执行。 async
-implemented API始终在返回的任务上放置任何异常。 所以,我想说任务返回API的期望是任务将收到异常。
在有骨头异常的情况下,您可以采用任何一种方式。 由于异常表示代码错误,因此引发错误并不重要。 例如,LINQ to Objects将始终立即引发骨头异常,而不是在枚举其返回的枚举器时。
但是,对于所有其他类型的异常,它们肯定应该返回返回的Task
。 就个人而言,我只是将所有异常放在返回的Task
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.