异步HttpHandler的请求是否可以在没有异常的情况下被中断?

时间:2009-04-24 13:34:32

标签: c# asp.net multithreading asynchronous

我们在IIS 6下使用ASP.NET 3.5中的异步HttpHandler,并且在我们的代码中,如果我们没有太多负载,我们想要执行外部API调用。我们已经定义了“太多负载”,这意味着如果我们同时有多个X请求到达此API,我们将跳过调用API。

为了实现这一点,我们将代码包装在Semaphore和Try / Catch / Finally中。我觉得这个代码没有办法在不释放信号量的情况下执行,但是通过一些额外的日志记录,我们发现在负载很重的情况下,release语句永远不会被调用。

代码是这样的:

static Semaphore requestLimiter = new Semaphore(500, 500);

...

String GetResultFromAPI() {
    if (!requestLimiter.WaitOne(0)) return null;

    try
    {
        // ... code to perform API call, with a timeout specified on the HttpWebRequest
        return result;
    } catch { /* ignore exceptions */ }
    finally
    {
        requestLimiter.Release();
    }
    return null;
}

我们已经看到HttpWebRequest超时的例外,所以我们很困惑这个代码如何导致requestLimiter信号量降到0并且永远不会恢复。

有没有人遇到过这个?有没有什么方法可以让异步HttpHandler在没有异常的情况下中断请求?

修改

显然ThreadAbortExceptions是一个讨厌的野兽,这个代码肯定会失败。我们没有显式调用Thread.Abort,也不认为HttpWebRequest会。但是,现在修改后的问题是:ASP.NET是否曾为异步http请求调用Thread.Abort?

2 个答案:

答案 0 :(得分:2)

在获取信号量和进入try catch块之间可能会遇到线程异常。

修改

也可能抛出一个绕过你的finally块的带外异常。您可以阅读有关Constrained Execution Regions here的更多信息。

答案 1 :(得分:2)

IIS可以关闭一个工作线程,该工作线程会触发一个ThreadAbortException,而ThreadAbortException并不总是被最终捕获。尽管如此,它们仍然被捕获。当IIS因任何原因杀死Web请求时,我遇到了这个问题。我的日志记录过程将在新线程中生成,以记录错误,而Thread.Abort仍然会终止我的日志记录过程。甚至尝试将日志记录线程放在finally {}中,IIS仍然会将其杀死。我永远无法弄清楚如何解决它。

无论如何,我会检查你的事件查看器是否有回收/杀死的工作线程,也许会检查你的应用程序池,并确保它设置为不经常回收/重启。