异步代码
ASP.NET Core和EF Core的默认使用异步编程。
Web 服务器的可用线程数量有限,在高负载情况下,所有可用线程都可能都在使用。 当发生这种情况时,服务器无法处理新的请求,直到线程被释放。 使用同步代码时,许多线程可能会被绑定,而实际上它们并没有做任何工作,因为它们正在等待 I/O 完成。 使用异步代码,当进程正在等待I/O 完成时,其线程将被释放,供服务器用于处理其他请求。 因此,异步代码可以更有效地使用服务器资源,并且使服务器能够无延迟地处理更多流量。
异步代码在运行时引入了少量的开销,但是对于低流量情况,性能下降可以忽略不计,而对于高流量情况,潜在的性能提升是巨大的。 在以下代码中,async 关键字, Task 返回值,await 关键字和 ToListAsync 方法共同构成异步执行代码。
public async Task<IActionResult> Index()
{
return View(await _context.Students.ToListAsync());
}
-
async
关键字告诉编译器为方法体生成回调函数,并自动创建返回的Task <IActionResult>
对象。 - 返回类型
Task<IActionResult>
表示正在进行的工作,其结果类型为IActionResult
。 -
await
关键字告诉编译器将该方法分为两部分。 第一部分以异步启动的操作结束。 第二部分被放入回调方法,该操作在操作完成时被调用。 -
ToListAsync
是ToList
扩展方法的异步版本。
当您编写使用实体框架的异步代码时,需要注意的一些事情:
- 只有会引发查询或将命令发送到数据库的语句才需要异步执行。 这包括例如
ToListAsync
,SingleOrDefaultAsync
和SaveChangesAsync
。 它不应该包括,例如,只是更改IQueryable的语句,类似var students = context.Students.Where(s => s.LastName == "Davolio")
这样的语句。 - EF上下文不是线程安全的:不要尝试并行执行多个操作。 当您调用任何异步 EF 方法时,请始终使用 await 关键字。
- 如果您想利用异步代码的性能优势,请确保您正在使用的任何库包(例如用于分页)也使用异步,如果他们调用任何导致查询发送到数据库的方法。