【问题标题】:What's the best way to call multiple async tasks in a Web API controller?在 Web API 控制器中调用多个异步任务的最佳方式是什么?
【发布时间】:2016-11-21 17:05:58
【问题描述】:

我正在尝试找到使我的 API 与多个依赖调用异步的最佳方法

<top routes...>
public async Task<IHttpActionResult> Post()
{
    /*... some sync items*/
    int userId= await _ef.saveUser();
    var siteInfo = callsite(userId);
    return await _ef.updateUserLastModified(); //need to wait for other 2
}

所以所有 3 个都需要按顺序运行,我可以创建一个私有函数将其作为任务运行吗?使其异步有什么好处吗?我基本上只是希望它处理这 3 个调用。

【问题讨论】:

  • 只需将这 3 个调用放在一个任务中即可。
  • 三个调用是否相互依赖?
  • 这段代码没有错。干净直接,除了第一个 await 应该在 _ef 前面。
  • 是的,我需要userId并且callsite()需要在updateUserLastModified()之前执行
  • 编辑离开之前

标签: c# .net asynchronous asp.net-web-api async-await


【解决方案1】:

你有什么好!假设最后一行取决于前两行,您的代码是等待异步调用并执行同步代码的正确方法:

public async Task<IHttpActionResult> Post()
{
   int userId = await _ef.saveUser();         // 1
   var siteInfo = callsite(userId);           // 2 
   return await _ef.updateUserLastModified(); // 3
}

在第 1 行完成之前,第 2 行不会执行,然后第 3 行将被等待并返回。方法结束之前的任何同步代码也将“正常”执行。

异步与多线程不同——它只是告诉编译器你需要等待一些异步事情完成后再继续的一种方式。

【讨论】:

  • 所以最好再做一个函数,这样第二部分也处于异步状态。
  • @DanParker Line 2?不,除非它本质上是异步代码(和等待的任务),否则没有理由重构它以“匹配”异步调用。一切都会正常工作。
【解决方案2】:

async 和await 的美妙之处在于您可以编写代码,使其读起来像同步代码。让我们分解一下你所拥有的,因为它是异步编程的正确实现。

public async Task<IHttpActionResult> Post()
{
   int userId = await _ef.saveUser();
   var siteInfo = callsite(userId);
   return await _ef.updateUserLastModified();
}

方法签名

我们定义了可公开访问的async 方法,它很高兴地返回一个Task&lt;IHttpActionResult&gt; 并命名为Post,太棒了。

身体线条 1

然后,我们声明并分配一个名为 userId 的变量,这是 _ed.saveUser() 调用的等待结果。这意味着saveUser 必须返回Task&lt;int&gt;,否则无法编译。 await 关键字在此方法块中是可能的,因为我们在方法签名中使用了 async 关键字。当我们awaitsaveUser 调用时,内部异步状态机捕获一个返回位置,然后立即将控制权返回给调用线程——允许它在其他地方工作。在一段未知的时间之后,当用户的保存完成时,控制将恢复它停止的位置(可能在同一个线程甚至线程池线程上)并分配userId 变量。

身体线条 2

一旦我们有了userId,然后我们才继续下一行。如果我们在上一行错误地省略了await,并且错误地将我们的userId 变量声明为var 而不是int,则会出现问题,因为该变量本来是Task&lt;int&gt; 而不是实现了我们想要的int。请注意,这是同步代码——它非常好,可以接受,实际上是鼓励的。不是每一条逻辑都需要async,而且“一路异步”这个短语实际上意味着别的东西。这意味着,例如,不是我们的 Post 方法是 void 并在 saveUser 上调用 .Result,而是一路异步。

身体线条 3

最后,我们返回 _ef.udateUserLastModified() 方法的等待结果。我们知道这也会返回一个Task&lt;IHttpActionResult&gt;。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-11
    • 2015-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-17
    相关资源
    最近更新 更多