Web Api C# - Task.Factory.startnew vs async

4
我正在我的终端点内进行日志记录,其中日志被发送到另一个服务。我不想将发送日志的开销影响到客户端使用的服务,并且即使有时日志传输失败我也不在意。因此,我一直在阅读关于如何简单地“fire and forget”的博客文章。我知道CPU密集型任务不应该使用异步,但我不明白IO相关任务有什么不同,通过IO我指的是调用其他服务的终端点,这种情况下是为了记录日志。
此外,我似乎得到了相互矛盾的观点。有些博客说你永远都不应该运行任何异步操作,因为这只会从线程池中获取一个或多个线程,与同步操作没有任何区别。
Microsoft在.NET 4.5中引入了async和await关键字,他们说你应该为整个终端点使用它们,但这是否仍然会从线程池中获取一个或多个线程?最后,我读过一些stackoverflow帖子,说使用Task.Factory.StartNew是可以的,因为.NET会管理它。
请问在发送日志到另一个服务的最佳实践方面,有人能澄清以上内容吗?我非常困惑。
我考虑使用nlog,因为它具有批处理和异步功能,但我仍不确定这是否是最佳方式。我不能使用像Hangfire这样的工具,因为我没有SQL后端。
提前感谢您的回答。

1
首先,给你一点功课:同步IO和异步IO有什么区别?使用异步IO相比同步IO有什么优势?IO完成端口(IOCP)在其中扮演了什么角色?当等待IO时,它们如何释放CPU资源? - spender
1个回答

8
一些博客说你永远不应该运行异步操作,因为这会从线程池中取走一个或多个线程。
不,这绝对不是真的。async 不使用线程池线程。(有关更多信息,请参见我的博客文章 There Is No Thread)。
最后,我读过一些 stackoverflow 帖子,说使用 Task.Factory.StartNew 是可以的,因为 .Net 会管理它。
同样,这也是错误的。StartNew 是一个危险的 API,不应该以这种方式使用。(有关更多信息,请参见我的博客文章 StartNew Is Dangerous)。
因此,我一直在阅读关于如何简单地启动和忘记的博客。

既然你“不在意有时候日志无法正常记录”,那我建议你使用 HostingEnvironment.QueueBackgroundWorkItem。QBWI 不会防止日志丢失,但它会尽力最小化日志丢失。只是简单地使用 Task.Run(或已过时和危险的 StartNew)将工作抛到线程池中,甚至不会尝试最小化日志丢失。当你需要更强大的功能时,可以考虑使用 Hangfire——例如,如果你必须确保日志正确记录,例如用于计费或审计。(有关更多信息,请参见我的博客文章ASP.NET 上的 Fire and Forget。)


谢谢。你的回答非常清晰,我会阅读你的博客文章。 - There is no spoon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接