使用WebApi进行I / O重异步任务的最佳实践

时间:2018-01-03 19:48:36

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

我通过web api 1.0响应HTTP POST的异步操作。收到此请求后,我需要做两件事:

  1. 执行数据库插入并将该新条目的标识返回给调用该函数的WebApp。
  2. 使用该身份执行大量I / O工作,WebApp和用户不会立即关注。
  3. 在一个完美的世界中,我会将数据放在某个队列中,并有一个小工作人员来处理队列。由于我不能立即这样做,在确保这项工作完成而不影响用户的情况下,最好的方法是什么。

    [HttpPost]
    public async Task<int> Post([FromBody]Object myObject)
    {
        return await new ObjectLogic().InsertObject(myObject);
    }
    public async Task<int> InsertObject(Object myObject)
    {
        var id = await new ObjectData().InsertObjectRoot(myObject);
        Task.Run(() =>  new ObjectData().ObjectWork(id, myObject));
        return id;
    }
    

    这是我提出的解决方案,但我认为必须有更好的东西,因为我从线程池中大量窃取线程直到我的工作完成。有没有更好的办法?我想我可以在我的InsertObject方法中使用ConfigureAwait(false),因为我真的不关心那里的上下文。

    // await async function but use ConfigureAwait
    public async Task<int> InsertObject(Object myObject)
    {
        var id = await new ObjectData().InsertObjectRoot(myObject);
        await new ObjectData().ObjectWork(id, myObject).ConfigureAwait(false);
        return id;
    }
    

1 个答案:

答案 0 :(得分:2)

一个问题是您的Web API是否应该执行除

之外的任何操作
  • 收到请求
  • 将其放在队列中
  • 使用id进行回复,表明已收到请求。

它会在某种程度上取决于您期望或可能会看到的负载。但是,如果您从一开始就关注可用线程的数量,那么答案可能就是您的Web API除了上述步骤之外什么都不做。

队列可以是文字队列,如MSMQ(或现在流行的任何东西。)或者它可以包含插入表中的记录。然后,单独的Windows服务可以处理该队列并执行I / O繁重的工作。它甚至不必在同一台服务器上。您可以单独缩放它。

如果用户确实需要某些最终指示,那么他们可以使用您返回的id定期轮询它。但对我来说,关键在于这句话:

  

使用该身份执行大量I / O工作, WebApp和用户不会立即关注。

Web应用程序的工作是提供响应 - IOW,执行用户所做的关心的事情。如果它是长时间运行的I / O繁重的工作,用户并不关心那么我会考虑卸载它。

相关问题