更改我的服务器端WebAPI以获得async / await的好处

试图了解服务器端的异步/等待使用。 我的理解是它只在释放线程时才有用。 如果我有:

[HttpGet] public async Task<IEnumerable> Get() { return await Task<IEnumerable>.Run(() => DoThingsAndGetResults()); } IEnumerable DoThingsAndGetResults() { // ...Do some CPU computations here... IEnumerable result = myDb.table.Select().ToList(); // entity framework // ...Do some CPU computations here... return result; } 

线程会被释放吗? 在这种情况下Async / Await是无用的吗? 从async / await获益的唯一方法是,如果我做了一些更大的更改并执行此操作:

 [HttpGet] public async Task<IEnumerable> Get() { return await DoThingsAndGetResultsAsync(); } async IEnumerable DoThingsAndGetResultsAsync() { // ...Do some CPU computations here... IEnumerable result = await myDb.table.Select().ToListAsync(); // entity framework // ...Do some CPU computations here... return result; } 

如果你想要实现的是释放线程,第二个例子更好。 第一个在整个操作中保持一个线程。

说明

async-await所做的就是简单地帮助您编写异步运行但“看起来”同步的代码。

异步代码有两个原因:

  1. 卸货 。 主要用于GUI线程或其他“更重要”的线程“。(在等待CPU操作完成时释放线程)。
  2. 可扩展性 。 主要用于服务器端以减少资源使用。 (在等待IO完成时释放线程)。

不出所料,原因与您的示例相符。

在第一个示例中,您在另一个线程上运行DoThingsAndGetResults (使用Task.Run )并等待它以异步方式完成。第一个线程正在释放,但第二个线程没有。

在第二个中,您一次只使用1个线程,并在等待IO(entity framework)时释放它。

当您必须等待IO操作(从文件读取,查询数据库,从Web服务器接收响应)时,异步方法最有用。

例如,当您的数据库提供程序支持像Entity Framework 6这样的异步查询时,可以使用异步。虽然它对CPU绑定操作(计算等)不是很有用。

请参阅ASP.NET MVC4异步控制器的相关答案- 为什么要使用?

使用An异步操作进行长时间运行io操作服务器端的好处之一是,就像数据库调用一样,你可以释放线程请求被处理,以便web服务器有更multithreading可用于处理新请求。 请注意,在使用默认任务计划程序时,这是正确的,该计划程序在线程池中的可用线程上计划任务。 当使用另一个taskcheduler时,效果可能会有所不同……