Может ли асинхронный запрос HttpHandler быть прерван без исключения? - PullRequest
2 голосов
/ 24 апреля 2009

Мы используем асинхронный HttpHandler в ASP.NET 3.5 под IIS 6, и в нашем коде мы хотим выполнить внешний вызов API, если мы не слишком загружены. Мы определили «слишком большую нагрузку», что означает, что если к этому API одновременно обращаются более X запросов, мы просто пропустим вызов API.

Для этого мы завернули наш код в семафор и попробовали / поймали / наконец. Мне кажется, что этот код не может быть выполнен без освобождения семафора, но с некоторыми дополнительными журналами мы видим, что при большой нагрузке оператор 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 когда-либо Thread.Abort для асинхронных http-запросов?

Ответы [ 2 ]

2 голосов
/ 25 апреля 2009

IIS может отключить рабочий поток, который вызовет исключение ThreadAbortException, и ThreadAbortException не всегда попадают в окончательный вариант. Они пойманы с уловом, хотя. У меня была эта проблема, когда IIS по какой-либо причине убивает веб-запрос. Мой процесс регистрации будет порожден в новом потоке, чтобы зарегистрировать ошибку, и Thread.Abort все равно прекратит мой процесс регистрации. Даже попытался добавить поток журнала в spawn {}, и IIS все еще убивает его. Я никогда не мог понять, как это решить.

В любом случае, я бы проверил вашу программу просмотра событий на предмет переработанных / уничтоженных рабочих потоков и, возможно, проверил бы пул приложений и удостоверился, что он настроен на частую перезапуск / перезапуск.

2 голосов
/ 24 апреля 2009

Вы можете получить исключение threadabort между взятием семафоры и попаданием в блок try catch.

Редактировать

Также возможно генерировать внеполосное исключение, которое обойдет ваш блок finally. Вы можете прочитать больше о Области ограниченного выполнения здесь .

...