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)
...那么唯一需要“交叉线”的是模型本身——没有其他代码逻辑依赖。
诚然,我可能正在做一个小问题 - 插入数据库不会花费但无论如何都需要一小部分时间......虽然它看起来应该很容易,而且我显然太固执而无法满足今晚“足够好”。
好的,找到了更多对我的场景有帮助的内容。它的基本要点似乎是不要这样做。
为了正确执行此操作,需要将其提交给分布式体系结构中的单独组件(例如,某种类型的消息或服务队列,可以单独提取以进行处理)。这似乎是完全脱离 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 方法的异步处理,但至少现在我知道我什么时候真正需要去做吧)