为什么我的IIS7应用程序池在从ASP.NET页面调用的DLL中发生异常后关闭?

前端之家收集整理的这篇文章主要介绍了为什么我的IIS7应用程序池在从ASP.NET页面调用的DLL中发生异常后关闭?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经阅读了 ASP.NET application pool shutdown problemIIS 7.5: problem with Application pool的帖子,但他们没有回答我的问题。

我有一个C#ASP.NET页面代码隐藏通过BIN目录提供的DLL实例化一个类,然后调用此实例上的一个方法。由于DataRow对象中的非现有列,DLL中的方法会抛出System.ArgumentException异常。事件日志显示以下错误

Source: ASP.NET 2.0.50727.0
Application ID: /LM/W3SVC/1/ROOT/...
Process ID: 9476
Exception: System.ArgumentException
Message: Column 'someColumn' does not belong to table.
StrackTrace:

ASP.NET页面中的调用代码方法调用包装在通用的try-catch块中。当我请求页面时,这将崩溃我的IIS实例的相应应用程序池,我的网站不再可用(错误503)。我手动需要重新启动应用程序池,网站再次工作。

更新
根据请求,从ASP.NET代码的try catch块:

try
{
    SomeExternalClass someExternalClass = new SomeExternalClass();
    someExternalClass.SomeMethod( someId );
}
catch( Exception ex )
{
    // "smp" is an instance of "StatusMessagePanel",a control we use on all pages 
    // to show error information,basically a div container with an icon.
    smp.ShowError( ex.Message ); 
}

现在我的问题是为什么在尝试访问不存在的DataRow列时抛出System.ArgumentException这个相对“简单”的异常,从而导致整个网站崩溃? ASP.NET页面的通用try-catch块也没有帮助,这也不是完全使整个网站不可用的原因,还是错误的假设?我从来没有想过这样可以使服务器(II)基本上下降。

有人告诉我,在访问列之前,我应该检查列存在:我知道这一点,遗留代码现在已经改变了,但这不是我上面提到的问题,我想知道为什么后果如此激烈。

更新2

在DLL内调用方法启动一个包装在try-catch块中的线程:

[...]
try
{
    ThreadStart starter = () => CreateReport(...)
    Thread thread = new Thread( starter );
    thread.Start();
    if( !thread.Join( TimeSpan.FromMinutes( 15 ) ) )
    {
        // Log some timeout warning
    }
    else
    {
        // Log information about successful report generation
    }
}
catch( Exception ex )
{
    // Log error information
}

解决方法

您可能会在 IIS’s Rapid Fail Protection功能自动关闭您的应用程序池,如您在链接的问题中所述。如果您检查事件日志,则可能会快速连续地抛出多个未处理的异常。

简单地说,在可配置的时间范围内(默认为5分钟5分钟)中的足够的未处理的异常将关闭AppPool,导致503 Service Unavailable响应。

功能背后的原因是,如果您的应用程序有问题,您可能不希望在每个后续请求中自动重新启动它,从而消耗资源并可能损坏数据。

我不得不承认,这不是我预期的“默认”行为。

查看Rick Stahls explanation,这有点更深入。

要真正解决这个问题,您需要捕获异常,或者阻止异常抛出(像@leppie建议)。未处理的异常应该会拆除整个执行过程(意味着单个请求/工作进程,而不是IIS) – 它使得.Net代码更容易调试,因为它不会隐藏错误或只是挂起应用程序。

请注意,在.Net 2.0中已更改:
http://msdn.microsoft.com/en-us/library/ms228965.aspx
http://support.microsoft.com/kb/911816

更新
根据上面的更新,如果从CreateReport()抛出异常,我不认为你的异常实际被捕获。该方法在单独的线程上执行:

如果没有一个,您需要在CreateReport()的正文中的try-catch:

public static void CreateReport() {
    try {
        throw new Exception("reducto");
    } catch {
        Console.WriteLine("done did.");
    }
}

猜你在找的asp.Net相关文章