假设我有一个异步方法,该方法使用Entity Framework从数据库中获取内容。例如:
public async Task<MyEntity> Get(string bar){
return await db.MyEntities.Where(x=>x.Foo==bar).SingleOrDefaultAsync();
}
这主要将由异步MVC或Web API控制器使用,并且工作正常。但是也许我偶尔也想在没有异步方法的控制台应用程序中使用它。我可以使用Task.Run
private static async Task MainAsync()
{
using(MyEntityService repo=new MyEntityService())
{
MyEntity myEntity=await repo.Get("foobar");
//do stuff
}
}
public static void Main()
{
Task.Run(async () =>
{
await MainAsync();
}).Wait();
}
我的问题是:与实现Get
方法的非异步版本相比,这样做有不利之处吗?假设我对这种级别的代码复杂性感到满意,是否有性能原因可以使非异步方法更好?
答案 0 :(得分:2)
在尝试给出类似于您的问题的答案之前,我觉得我需要让您意识到一个重要的问题,那就是对于C#7.1或更高版本,您可以使用异步Main方法。您可以在What's new in C# 7.1中阅读有关此内容的更多信息,但请阅读TL; DR,在将项目切换为使用C#7.1或更高版本或“最新”后,可以执行以下操作:
public class Program
{
public static async Task Main(string[] args)
{
using(MyEntityService repo=new MyEntityService())
{
MyEntity myEntity=await repo.Get("foobar");
//do stuff
}
}
}
现在,让我们尝试回答您的问题。请记住,我对async / await的了解可能有缺陷/不完整,因此可能会浮现出其他更好的答案。
这样一来,异步将为您的代码添加的最重要内容是什么? 复杂度。
每当您将一个方法声明为async
时,整个方法编译都会更改。整个过程变成一个状态机,并被重写和移动。如果以后再对程序进行反编译,除非反编译器是真正的高级类型,否则反编译后的代码将看起来像原始程序一样。
现在,此状态机是否会在执行时间或内存使用方面增加程序执行的开销?不,不是真的。
一个不同的问题是,使用异步版本和使用非异步版本会增加多少开销,而没有办法解决。整个机制以及所有不同的选项可能意味着有很多,或者可能几乎没有,这取决于您使用的实际API以及它的作用/方式。
关于异常,您将要处理的问题之一。当涉及到声明为async
的方法时,堆栈跟踪就变得很有趣。
例如,给定这个简短的程序(我使用LINQPad运行):
async Task Main()
{
await Test1();
}
public static async Task Test1()
{
await Task.Delay(1000);
throw new Exception("Test");
}
您可能希望异常的堆栈跟踪包含Main
,但是,由于throw
语句是在任务被延迟后“浮出水面”之后执行的,因此它将由一些框架代码执行,并且堆栈跟踪实际上看起来像这样:
at UserQuery.<Test1>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at UserQuery.<Main>d__0.MoveNext()
我想您真正在寻找的是一些有关如何处理异步代码的准则,而我能做到的最好的是这些准则:
.Wait()
或.Result
获得结果并了解完全您在做什么 (请记住,我并没有以任何方式谈论API的方法在做什么;我的假设是,如果API提供了异步方法,则有理由它)
答案 1 :(得分:1)
如果您没有任何I / O绑定操作(例如从数据库/磁盘或网络读取),那么非异步方法会更好,因为异步/等待会产生额外的额外费用。否则,由于释放IIS的线程
,异步操作可能是一个不错的选择