Web Api – 火与忘记
我有一个Web API的动作,我需要运行一些任务而忘记这个任务。 这就是我的方法现在的组织方式:
public async Task DoSth() { await Task.Run(...); ..... //Do some other work }
事情是,显然它停在等待线等待它完成后才继续工作。 我需要“解雇并忘记”我是否应该在没有任何异步等待的情况下调用Task.Run()?
我需要“开除并忘记”
我有一篇博文,详细介绍了几种不同的ASP.NET方法 。
总结:首先,尽量不要忘掉。 这几乎总是一个坏主意。 你真的想“忘记”吗? 如在,不关心它是否成功完成? 忽略任何错误? 在没有任何日志通知的情况下接受偶尔“丢失工作”? 几乎总是,答案是否定的,“即发即忘”不是合适的方法。
可靠的解决方案是构建适当的分布式架构。 也就是说,构造一个表示要完成的工作的消息,并将该消息排队到可靠的队列(例如,Azure队列,MSMQ等)。 然后有一个独立的后端处理该队列(例如,Azure WebJob,Win32服务等)。
我应该在没有任何异步等待的情况下调用Task.Run()吗?
不,这是最糟糕的解决方案。 如果你必须做好事,而且你不愿意建立分布式架构,那么考虑一下Hangfire。 如果这对您不起作用,那么至少应该通过HostingEnvironment.QueueBackgroundWorkItem
或我的ASP.NET后台任务库向ASP.NET运行时注册您的牛仔背景工作。 请注意,QBWI和AspNetBackgroundTasks都是不可靠的解决方案; 他们只是尽量减少你失去工作的机会,而不是阻止它。
在asp.net中,真正的火灾和遗忘任务可能很困难,因为它们经常会因为它们是作为其一部分创建的请求而死亡。
如果您使用的是4.5.2+,则可以使用QueueBackgroundWorkItem来运行任务。 通过这种方法注册任务,AppDomain将尝试延迟关闭,直到它们全部完成,但仍然可能存在它们在完成之前被杀死的情况。 这可能是最简单的事情,但值得一读,以确切了解哪些实例可以导致取消作业。
HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => { await Task.Run(...); });
有一个名为hangfire的工具,它使用持久存储来确保任务已完成,并具有内置的重试和错误记录function。 这更适用于“后台任务”,但确实适合火灾和遗忘。 这是相对容易设置和提供各种后备存储,我不记得确切的细节,但有些需要许可证,有些则不需要(如MSSQL)。
永远不要忘记,因为那样你就不会看到任何错误,这会导致一些非常尴尬的故障排除,如果出现问题(让任务方法做自己的exception处理不能保证工作,因为任务可能不会首先成功开始)。 除非你真的不介意任务是否做了什么,但这是非常不寻常的(因为,如果你真的不在乎,为什么要首先执行任务)? 至少,使用延续创建您的任务:
Task.Run(...) .ContinueWith(t => logException(t.Exception.GetBaseException()), TaskContinuationOptions.OnlyOnFaulted ) ;
根据您的需求,您可以使其更加复杂。
在Web API的特定情况下,您可能实际上希望在完成请求之前等待后台任务完成。 如果你不这样做,你就会留下在后台运行的东西,这些东西可能会歪曲你的服务真正需要多少负载,或者如果客户端发出太多请求并且你没有采取任何措施来阻止它们,那么甚至会完全停止工作。 您可以收集任务并在最后发出await Task.WhenAll(...)
以实现该目的; 通过这种方式,您可以在后台任务逐渐消失的情况下继续执行有用的工作,但在完成所有操作之前,您不会返回。
对于火灾和遗忘,请使用此function
Task.Factory.StartNew(async () => { using (HttpClient client = new HttpClient()) { await client.PostAsync("http://localhost/api/action", new StringContent("")); } });
我使用HangFire 。
这对我来说是最好的。
在.NET和.NET Core应用程序中执行后台处理的简便方法。 无需Windows服务或单独的过程。
以持久存储为后盾。 开放和免费用于商业用途。
我同意其他人的意见,你不应该忘记你的电话。 但是,要回答您的问题,如果从Task.Run()行中删除等待,则调用将不会阻塞,如此处所示
public async Task DoSth() { Task.Run(...); ..... //Do some other work while Task.Run() continues in parallel. }
这里有一些post推动“永不发火,忘记”,错误等。
事实是,从某些观点来看,这并没有错。 在某些方面错误地描述了。
真正应该说的是“用户应该能够解雇并忘记,但它仍然应该告诉开发人员/所有者。”
一个很好的例子是在网站上联系我们表格。 客户填写表格并在幕后通过电子邮件向网站所有者发送电子邮件。 有些电子邮件服务器需要很长时间来处理发送,因此像Hangfire这样的软件包(我会使用它)会将其发送到网络服务器“线程”之外的另一个进程。
是的,如果发生错误,这应该以某种方式告知开发人员/所有者(并保留联系人详细信息)。 但这绝不应该告诉潜在的联系人。 (除非你想失去潜在客户)
为了调用fire并忘记WebApi方法,我使用以下代码来确保它返回OK响应 。 我的情况是,登录时创建的不记名授权令牌存储在cookie中:
... FireAndForget().Wait(); ... private async Task FireAndForget() { using (var httpClient = new HttpClient()) { HttpCookie cookie = this.Request.Cookies["AuthCookieName"]; var authToken = cookie["AuthTokenPropertyName"] as string; httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken); using (var response = await httpClient.GetAsync("http://localhost/api/FireAndForgetApiMethodName")) { //will throw an exception if not successful response.EnsureSuccessStatusCode(); } } }
- ASP.NET MVC消息处理程序与Web API消息处理程序
- 如何在ASP.NET Core Web Api中完成版本控制
- validation在unit testing中失败
- 运行代码第一次迁移update-database时出错
- 需要调试从客户端计算机请求的Web API服务 – 需要帮助,我该怎么做?
- WebApi XML反序列化 – 具有多个子节点的节点未正确反序列化为子节点对象数组
- 获取相关实体ASP.NET WebApi OData v4导致“未找到与请求URI匹配的HTTP资源”
- 为什么Web API不会反序列化,但JSON.Net会?
- ASP.NET WebApi IExceptionLogger不捕获exception