从控制器返回,无需等待异步方法完成

jle*_*ach 5 c# asynchronous asp.net-web-api

我读过自己的蓝色,希望有一个简单的答案。

我有一个 Web API 可以处理来自各种“野外”应用程序的遥测 在我的一个控制器中,我想接收一个请求,将错误记录到我的中央监控数据库并尽可能立即返回响应(我没有真正的了解调用者端性能可能有多重要的方式,并且已经有一个对初始 Web 服务请求的重大影响)。

基本上,我正在寻找的是这样的:

public IHttpActionResult Submit() {
    try {
        var model = MyModel.Parse(Request.Content.ReadAsStringAsync().Result);

        // ok, I've got content, now log it but don't wait
        // around to see the results of the logging, just return
        // an Accepted result and begone

        repository.SaveSubmission(model); // <-- fire and forget, don't wait

        return Accepted();

    } catch (Exception)
        return InternalServerError();
    }
}
Run Code Online (Sandbox Code Playgroud)

看起来它应该是直截了当的,但显然不是。我已经阅读了许多不同的帖子,从是的,只是使用 Task.Run()这是一个可怕的错误,你永远无法实现你想要的!

我的场景中的问题似乎是这个进程可能会在进程中终止,因为它运行在 ASP.NET 工作进程上,而不管调用异步方法的不同方法的泥潭(我已经用了最后两个几个小时左右阅读各种SO问题和Stephen Cleary博客......哇)。

如果在这种情况下的潜在问题是我“触发并忘记”的方法绑定到 http 上下文并受到 ASP.NET 工作进程的提前终止,那么我的问题就变成了......

有没有办法从那个 ASP.NET 上下文中删除这个方法/任务/进程?一旦该请求被解析到模型中,我自己就不再需要在 http 上下文中进行操作了。如果有一种简单的方法可以将它移出那里(从而让事情运行,除非网站/应用程序池重新启动),那就太好了。

为了尽职调查,假设我摆脱了控制器中的存储库上下文并将其委托给其他上下文:

public IHttpActionResult Submit() {
    try {
        var model = MyModel.Parse(Request.Content.ReadAsStringAsync().Result);

        SomeStaticClass.SaveSubmission(model); // <-- fire and forget, don't wait

        return Accepted();

    } catch (Exception)
        return InternalServerError();
    }
}
Run Code Online (Sandbox Code Playgroud)

...那么唯一需要“交叉线”的是模型本身——没有其他代码逻辑依赖。

诚然,我可能正在做一个小问题 - 插入数据库不会花费但无论如何都需要一小部分时间......虽然它看起来应该很容易,而且我显然太固执而无法满足今晚“足够好”。

jle*_*ach 9

好的,找到了更多对我的场景有帮助的内容。它的基本要点似乎是不要这样做。

为了正确执行此操作,需要将其提交给分布式体系结构中的单独组件(例如,某种类型的消息或服务队列,可以单独提取以进行处理)。这似乎是完全脱离 ASP.NET 工作进程的唯一方法。

一篇 S/O 评论(到另一篇 S/O 帖子)让我看到了两篇我在发布之前还没有看过的文章:一篇由 Stephen Cleary 撰写,另一篇由 Phil Haack 撰写。

SO 感兴趣的帖子:如何在 ASP.NET Web API 中排队后台任务

Stephen 在 ASP.NET 博客文章中的“火与忘”(很棒,希望我能先找到它):http : //blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html

和菲尔的文章:http : //haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx/

Stephen 的以下项目可能也很有趣:https : //github.com/StephenCleary/AspNetBackgroundTasks

我以为我会删除我的问题,但后来发现我花了很长时间才找到我的答案,也许另一个问题不会对我造成伤害......

(在这种特殊情况下,提交到另一个服务的时间与写入数据库的时间差不多,所以我可能会放弃这个 api 方法的异步处理,但至少现在我知道我什么时候真正需要去做吧)