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

时间:2016-07-19 00:16:52

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

我试图找到使用多个相关调用使我的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个电话。

2 个答案:

答案 0 :(得分:3)

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

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

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

Async与多线程不是一回事 - 它只是告诉编译器在继续之前需要等待一些异步事情完成的方法。

答案 1 :(得分:1)

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

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

方法签名

我们定义了可公开访问的async方法,可以快乐地返回Task<IHttpActionResult>并命名为Post,非常棒。

Body Line 1

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

Body Line 2

一旦我们有了userId,那么我们才会继续下一行。如果我们错误地省略了前一行中的await并且错误地将我们的userId变量声明为var而不是int,那么因为变量会有问题是Task<int>而不是我们想要的具体化int。请注意,这是同步代码 - 这是完全正常和可接受的,实际上是鼓励的。并非每一条逻辑都需要async,并且短语&#34; async is as way&#34;实际意味着别的东西。这意味着,例如,Post方法不是void方法,而是.Result上的saveUser,而是一直异步。

Body Line 3

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