我想将任务并行库用于一些计算密集型任务,但一位同事告诉我,IIS 创建工作线程的开销很大。
当您调用 Task.Factory.StartNew()... 说 100 次时,我不太确定会发生什么。IIS 如何处理这个问题?是一个巨大的风险,还是有办法让这对应用程序非常有益?
我想将任务并行库用于一些计算密集型任务,但一位同事告诉我,IIS 创建工作线程的开销很大。
当您调用 Task.Factory.StartNew()... 说 100 次时,我不太确定会发生什么。IIS 如何处理这个问题?是一个巨大的风险,还是有办法让这对应用程序非常有益?
第一个任务!=线程。您可能有许多任务由少数线程(已经被池化)提供服务。
作为一般规则,我反对在 Web 服务器上运行长时间运行的进程。保持长时间运行的作业存在大量问题,并且您往往会降低 Web 服务器的可伸缩性,尤其是在并行处理长时间运行的 CPU 密集型作业时。不要忘记在机器上运行的最佳线程数等于“逻辑”内核的数量。您希望避免创建过多的线程(每个托管线程都会消耗类似兆的开销)。运行 cpu 密集型作业会占用 cpu 时间来处理请求。
在我看来,在 Web 服务器上使用 tpl 的最佳方式是使用它的目的是让请求尽可能无阻塞,这样可以用最少的请求来处理最多的请求。线程。请记住,许多人认为通过高度异步处理请求获得的额外规模不值得额外的复杂性。取决于你的具体情况。
简而言之,在 Web 服务器上运行许多长时间运行的 cpu 绑定任务会危及您的可扩展性。如果您使用任务、线程、后台工作者或线程池,这并不重要。它归结为同一件事。
抽象的一大Task
优点是它抽象了创建线程。这意味着 TPL(实际上是ThreadPool
)可以决定实际线程的最佳数量是多少。因此,创建 100Task
秒很可能不会创建 100Thread
秒。因此,您不必担心创建Thread
s 的开销。
但这也取决于Task
它们是什么样的。如果您有 100Task
秒执行一些长的 IO 绑定操作,因此它们大部分时间都阻塞,那么这不是 TPL 的好用处,您的代码将非常低效(实际上您可能最终得到 100Thread
秒)。
另一方面,如果你有 100 个 CPU-bound,相对较短Task
的 s,那是 TPL 的最佳点,你会得到很好的效率。
如果您真的关心效率,您还应该知道Task
s 确实有一些开销。Task
因此,在某些情况下,将多个s 合并为一个较大的 s 以减少开销可能是有意义的。或者您可以使用已经这样做的东西:Parallel.ForEach
或者Parallel.For
,如果它们适合您的用例。作为另一个优点,使用它们的代码将比Task
手动使用 s 更具可读性。
仅仅创建一个服务来处理这项工作怎么样?你会在扩展方面做得更好,并且可以很好地隔离那个工作单元......即使工作是计算绑定的。
在我看来 - 不要Thread Pool/BackgroundWorker/Thread
在 ASP.NET 中使用。在您的情况下,TPL
简单地包装线程池。它通常比它的价值更麻烦。
任何主机的线程开销都是相同的。与 IIS 无关,至少在性能方面。
还有其他担忧。例如,在应用程序关闭时,用户线程被粗暴地中止。