Шаблон для Допускающего повторное использование асинхронного HttpHandler

Я в настоящее время разрабатываю пользовательский HttpHandler (для сжатия/объединения CSS, но это не имеет значения для этого вопроса).

Я запустил с простого reusable=true синхронного HttpHandler как, все мы знаем.

Теперь я пытаюсь улучшить его до асинхронного обработчика (поскольку это использует функциональность IO, и это используется на очень занятом веб-сайте).

Моя первая попытка (и это, кажется, работает хорошо):

Action<HttpContext> asyncProcessRequest;

public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
    asyncProcessRequest = new Action<HttpContext>(ProcessRequest);
    return asyncProcessRequest.BeginInvoke(context, cb, extraData);
}

public void EndProcessRequest(IAsyncResult result)
{
    asyncProcessRequest.EndInvoke(result);
}

public virtual void ProcessRequest(HttpContext context)
{
    // real work
}

Это - httphandler одноразового использования (как от того, что я считал, IsReusable должен быть ложью, потому что этот обработчик имеет состояние (asyncProcessRequest поле).

Теперь я хочу сделать это допускающим повторное использование. Таким образом, моя первая мысль состояла в том, чтобы создать словарь IAsyncResult / Действие как это:

IDictionary<IAsyncResult, Action<HttpContext>> asyncProcessRequests;

public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
    if (asyncProcessRequests == null)
    {
        asyncProcessRequests = new Dictionary<IAsyncResult, Action<HttpContext>>();
    }

    var request = new Action<HttpContext>(ProcessRequest);
    var result = request.BeginInvoke(context, cb, extraData);
    asyncProcessRequests.Add(result, request);
    return result;
}

public void EndProcessRequest(IAsyncResult result)
{
    Action<HttpContext> action;
    if (asyncProcessRequests.TryGetValue(result, out action))
    {
        action.EndInvoke(result);
    }
}

Действительно ли это - корректный шаблон? или я - путь прочь?

Это, кажется, работает (я не получаю ошибок или странного поведения), но прежде, чем поместить это в производство, я хотел бы проверить с кем-то, у кого есть больше опыта, чем я в записи этих обработчиков Http..

Заранее спасибо!

6
задан Remco Ros 5 February 2010 в 15:16
поделиться

2 ответа

В общем, для асинхронного шаблона вы должны использовать параметр состояния, который вы передаете в метод BeginXxx в качестве последнего параметра (вы назвал его extraData ).

Таким образом, вы можете создать вспомогательный класс, содержащий (исходные) extraData , а также любое дополнительное состояние, необходимое для обработки завершения запроса.

Однако в вашем конкретном случае я считаю, что вы ничего не ускоряете с помощью шаблона async. Хотя он работает, он в основном только добавляет накладные расходы, поскольку вы вызываете делегата в асинхронном режиме, который ничего не делает, кроме отправки вызова пулу потоков для обработки вызова. Следовательно, пока у вас нет нескольких делегатов, работающих одновременно через асинхронные вызовы, вы не получите особой выгоды. Поскольку веб-запросы уже являются многопоточными, я не думаю, что это улучшит производительность; напротив, вы столкнетесь с риском истощения пула потоков.

Правильная и эффективная обработка асинхронного кода - непростая задача. Вы можете извлечь из этого выгоду, если выполняете асинхронные вещи, такие как чтение данных из файла или сетевого подключения, или при вызове внешних компонентов, которые поддерживают асинхронный вызов (например, вызов веб-службы или базы данных).

4
ответ дан 17 December 2019 в 02:28
поделиться

Если я правильно помню, IsReusable указывает ASP.NET, что ваш обработчик не должен быть уничтожен после обработки запроса, и тот же экземпляр можно использовать для обработки последующих запросов. Т.е. один экземпляр объекта-обработчика не обрабатывает несколько запросов одновременно.

2
ответ дан 17 December 2019 в 02:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: