【问题标题】:How can long running thread work inside web application长时间运行的线程如何在 Web 应用程序中工作
【发布时间】:2013-07-17 13:16:58
【问题描述】:

所以我在 MVC 控制器方法中有以下代码:

public ActionResult ProcessFile () 
{
    ThreadStart threadStart = new ThreadStart ( ()=>{

        // Doing some long processing that takes 20 minute 
    } );

    Thread thread = new Thread(threadStart); 
    thread.Start();
}

这里的问题是,当向这个控制器方法发送多个请求时,线程会被杀死。 我需要 Thread 继续工作直到处理结束,这似乎是一个资源问题,占用的资源越多,线程可以继续工作的越少。 如果我从 Windows 应用程序或服务运行该进程,它可以完美运行,只有从 Web 应用程序启动时才会出现问题。

【问题讨论】:

  • 如果一个对象...比如thread 超出范围,它可能会被垃圾回收。我强烈建议您使用 Task 来处理此类事情,因为您不需要保留对它的引用。
  • 我使用了 Task ,由于某种原因,Tasks 比 Thread 更频繁地被取消,即使我将 Task 归因于(长时间运行)。
  • 您是否尝试访问该线程上的任何 ASP.net 上下文?
  • nop ,所有的过程都是分析数据并将它们存储在 csv 文件中。
  • 该线程中是否抛出异常?

标签: c# asp.net asp.net-mvc iis-7 threadpool


【解决方案1】:

理想情况下,您不应在 IIS 7 中为 Web 请求创建线程(用于长时间运行的后台作业)。

如果应用程序池/AppDomain 重新启动,线程将停止,这可能由于多种原因而发生,例如 bin 文件夹内容的更改、web.config 的更改、一段时间的不活动、资源阈值达到(例如内存使用)。事实上,AppDomain 默认会定期重启,因为它已经存活了 x 时间。

因此,应该使用作业队列和后台作业运行器来实现长时间运行的任务,例如控制台应用程序或 Windows 服务(重要的是,不在 IIS 上下文中运行),处理这些作业。

Web 请求应该简单地将作业添加到队列中,允许后台作业运行器在作业出现时获取它们。

Can I use threads to carry out long-running jobs on IIS?这里已经回答了一个类似的问题

编辑:一个严重不推荐的替代方案

如果您坚持或别无选择,只能在 IIS 进程中运行后台作业,您需要考虑允许后台作业自发停止,并允许其从停止时停止的位置重新启动。

您可以拥有一个可以轮询的 URL,以触发未完成作业的重新启动。

我过去见过这项工作,实施的复杂性会根据后台工作的要求而有所不同。

您会发现随着后台作业的反复启动和终止,服务器可能会开始出现性能问题。

【讨论】:

  • 当进程运行时,由于计算,CPU 高达 70%。在我的本地 IIS 上它永远不会失败我可以处理很多请求,这个过程会变慢但永远不会失败。在云服务器中,线程在第二个或第三个之后被杀死。
  • 最有可能发生的是云服务器(azure/appharbor?),当您使用过多的 CPU 周期或内存时,将配置为重新启动 AppDomain。这将确保硬件上运行的其他应用的服务质量。
  • 好点,将此问题标记为已回答的另一个原因
【解决方案2】:

虽然上面的答案是可以接受的,但在您的网络应用程序中托管诸如任务之类的长期运行服务还是有一些好处的。

Rick Strahl 在这里有一篇关于它的博文: Use-IIS-Application-Initialization-for-keeping-ASPNET-Apps-alive

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-19
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 2011-02-27
    • 1970-01-01
    相关资源
    最近更新 更多