在Web应用程序中使用ThreadPool.QueueUserWorkItem是否有任何缺点。

时间:2016-12-21 15:15:01

标签: c# asp.net-mvc

我对这个主题进行了一些研究,但我无法找到预期的答案。在我的应用程序中,我使用了

  

ThreadPool.QueueUserWorkItem

喜欢以下方式。

ThreadPool.QueueUserWorkItem(o => CaseBll.SendEmailNotificationForCaseUpdate(currentCase, caseUpdate));

我的应用程序在asp.net mvc&我已经处理了所有后台任务,这些任务不需要在用户操作上执行以加快执行速度。快速的用户响应。 现在我想知道,使用 ThreadPool.QueueUserWorkItem 是否有任何不好的方面当我们有更多的应用程序受众。

2 个答案:

答案 0 :(得分:2)

不,你永远不应该使用它。我可以写出很多理由,但你应该阅读Scott Hansleman这篇天才恕我直言的这篇文章

http://www.hanselman.com/blog/ChecklistWhatNOTToDoInASPNET.aspx

"可靠性和性能":

  

Fire-and-Forget Work - 避免使用ThreadPool.QueueUserWorkItem,因为您的应用程序池可能随时消失。如果必须,可以将此工作移到外面或使用WebBackgrounder。

因此,按照建议,不要使用ThreadPool.QueueUserWorkItem。一个很好的替代方案是:

https://www.asp.net/aspnet/overview/web-development-best-practices/what-not-to-do-in-aspnet-and-what-to-do-instead#fire

编辑:正如@ Scott-Chamberlain所提到的,这是一个更好的链接: http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx

答案 1 :(得分:1)

这实际上取决于你将要做什么,但一般来说,你可能会担心:

  • 持续性。托管池中的线程是后台线程。当应用程序回收时它们会死亡,这通常是不可取的。在您的情况下,您想发送电子邮件。想象一下,如果你的进程在线程执行之前由于某种原因而死亡。您的电子邮件永远不会被发送。
  • 本地存储是共享的,这意味着如果使用它,您需要确保最后一个线程没有剩余空间。适用于标记为ThreadStaticAttribute的字段。

我建议您实施一个作业方案,在那里您可以在某处安排作业,并从该列表中实际读取一些其他组件(例如数据库)并执行该作业,然后将其标记为完成。这样它会在应用程序卸载过程中持续存在,没有内存重用,您可以限制性能。您可以在应用程序内部实现处理组件,如果愿意,甚至可以在Windows服务中实现。