【问题标题】:What happens to running tasks when IIS recyclesIIS 回收时运行任务会发生什么
【发布时间】:2013-01-25 17:16:54
【问题描述】:

为了帮助提高客户端的性能,我将请求的处理转移到任务上。这样做是因为处理通常需要一些时间,而且我不希望客户端等待一段时间才能获得 200 响应。将工作卸载到任务上的 Web 服务始终在处理帖子。

public void ProcessRequest(HttpContext context)
{
    // check for bad requests -- return 400

    // get copy of the context input stream

    Task.Factory.StartNew(() =>
    {
        ProcessRequest(contextInputStreamCopy);
    });
}

private void ProcessRequest(Stream inputStream)
{
    try
    {
        // process input stream
    }
    catch(Exception ex)
    {
        // any server error that would normally result in 500 response are not
        // exposed to the clients, the clients are to see 200 when the server 
        // encounters an error
    }
}

所以我的问题是当 IIS 回收或网站停止时这些任务会发生什么。

【问题讨论】:

  • 虽然这是一个很好的一般性问题,但请考虑一下它是否真的适用于您的情况。既然您似乎并不关心任务的结果或任务中的任何错误,为什么还要关心它在回收/崩溃时会发生什么?
  • @AlexeiLevenkov 他可能关心已经发生的副作用。如果它正在执行诸如将批量数据插入数据库之类的操作,您不希望它消失或更糟,请保持一半完成。该任务可能会执行 UI 中未显示的错误处理。
  • @AlexeiLevenkov 我确实关心处理的结果,它的客户不应该关心任何错误。我的理解是,任务主体中的一般 try/catch 应该可以防止任务在大多数情况下遇到异常,因此任务会被触发并忘记,它会在完成时完成。
  • @millimoose 你说得对,任务的中止导致我的数据处于错误状态。
  • 我明白了。请注意,您感兴趣的问题实际上是“如果我在崩溃/杀死我的 AppDomain 中运行我的代码的进程,如何为我的数据实现事务支持”......我建议接受解释 IIS 行为的答案回收并提出单独的问题,说明您可以在支持事务的情况下进行数据库的原因。

标签: c# asp.net c#-4.0 iis iis-7.5


【解决方案1】:

当 IIS 回收时,它会等待所有线程完成并退出 - 直到池中的超时值。在那之后,他们会杀死所有正在运行的线程并重新开始。

因此,您可以使用Application_End 函数向您的线程设置信号以在应用程序请求在globa.asax 关闭时停止。

【讨论】:

  • 如果我在创建任务时将任务添加到列表中,然后在Application_End 中执行Task.WaitAll 会等到所有任务完成吗?正如它确实出现的那样,我偶尔会出现线程中止并且它留下的数据是一种错误的状态。
  • @JGinSD 是的,您也可以这样做 - 我也这样做了,并且还发出停止信号。但我说你他们等到超时值。如果可以的话,您可能需要提高池中的超时值。
  • 啊,所以即使我在Application_End 等待它仍然有可能达到超时。
  • @JGinSD 是的,可以等待多长时间存在超时。 Shutdown time limit (seconds) 在泳池上
  • 是的,它已经设置得相当高了,所以我可能需要重新考虑我们的整体策略,也许像 Cuong Le 建议的那样做一些事情。
【解决方案2】:

IIS 回收时正在运行的任务会发生什么

当 IIS 回收时,它只会相应地降低您正在运行的任务。如果您的任务需要一些时间,您应该考虑在单独的进程上运行您的任务。一种纠正方法是使用队列(MSMQ、RabbitMQ ...)来存储您的任务并使用另一个进程从队列中选择您的任务以运行。为此,您可以使用带有调度程序的 Windows 服务或控制台主机。

More information 来自 Phil Haack:

当 ASP.NET 拆除 AppDomain 时,它会尝试刷新现有请求,并在拆除 App Domain 之前给它们时间来完成。 ASP.NET 和 IIS 会考虑它们知道正在运行的代码,例如作为请求的一部分运行的代码。

问题是,ASP.NET 不知道在使用计时器或类似机制产生的后台线程上完成的工作。它只知道与请求相关的工作。

【讨论】:

    猜你喜欢
    • 2020-06-18
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-11
    • 1970-01-01
    相关资源
    最近更新 更多