什么';是在Web API控制器中调用多个异步任务的最佳方式

本文关键字:异步 任务 方式 最佳 调用 是在 Web 控制器 API 什么 | 更新日期: 2023-09-27 17:57:29

我正在努力寻找使我的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个调用。

什么';是在Web API控制器中调用多个异步任务的最佳方式

您拥有的一切都很好!假设最后一行取决于前两行,那么您的代码是等待异步调用和执行同步代码的正确方式:

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

直到第1行完成,第2行才会执行,然后等待第3行并返回。方法结束前的任何同步代码也将"正常"执行。

异步与多线程不是一回事——它只是告诉编译器在继续之前需要等待一些异步操作完成的一种方式。

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

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

方法签名

我们定义了我们的可公开访问的async方法,该方法愉快地返回一个Task<IHttpActionResult>,并命名为Post,非常好。

车身线条1

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

车身线条2

一旦我们有了userId,那么只有到那时我们才能继续下一行。如果我们错误地省略了前一行的await,并错误地将userId变量声明为var而不是int,这将是有问题的,因为该变量将是Task<int>,而不是我们想要的物化int。请注意,这是同步代码——这是非常好的、可接受的,事实上也是值得鼓励的。并不是每一个逻辑都需要是async,短语"async all way"实际上意味着其他东西。这意味着,例如,我们的Post方法不是void,而是在saveUser上调用.Result,而是一直异步。

车身线条3

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