2009-12-21 2 views
5

У меня есть веб-приложение, которое в значительной степени зависит от веб-служб. Все с сервисами выполняется асинхронно и с AddOnPreRequestHandlerExecuteAsync. Во всяком случае, большинство моих звонков работают нормально, но некоторые из них возвращаются из своих асинхронных вызовов службы, чтобы найти нулевой объект HttpContext.Current.Response/Request в концеprerequest, который, конечно, ошибки в тот момент, когда я пытаюсь использовать. Оба объекта (Response and Request) доступны/не являются нулевыми для beginprerequest неудачных вызовов и работают в концепроцесса других вызовов).Асинхронные HttpWebRequests и нулевой объект HttpContext.Current.Response/Request

Кто-нибудь сталкивается с подобным или может предположить, что может быть проблемой?

Обновление: Кажется, вы нашли решение, если я создаю переменную для HttpApplication on Init (из HttpModule, все это происходит), из HttpContext можно получить доступ к этой переменной.

Обновление: передача HttpApplication или HttpContext.Current в функции begin имеет ту же проблему. Когда они передаются как часть «состояния» асинхронного вызова, они заканчивают нулевым значением в конце функции, даже если они действительны в функции begin.

Обновление: я добавил несколько протоколов и обнаружил, что Асинхронный вызов, который я делаю, возвращает правильно, результаты там, функция обратного вызова вызывается правильно.

ответ

0

Возможно, было найдено решение, если я создаю переменную для HttpApplication on Init (из HttpModule, в которой все это происходит), из HttpContext можно получить доступ к этой переменной.

+0

Можете ли вы описать с подробностями, как вы решили проблему – omoto

+0

В моем HttpModule у меня есть переменная типа HttpApplication. В вызове функции init() я устанавливаю эту переменную в HttpApplication, которая передается init. В BeginPreRequestHandlerExecute и EndPreRequestHandlerExecute я ссылаюсь на текущий HttpContext, используя oApplication.Context, oApplication - это имя переменной HttpApplication в моем HttpModule. – aepheus

5

Я подозреваю, что знаю проблему, с которой вы столкнулись. Ответ, почти наверняка, заключается в замене использования HttpWebRequest на WebClient и использовании методов * Async для WebClient.

Вот длинное объяснение: есть две совершенно разные модели программирования Async: IAsyncResult Async Pattern и Event-based Asynchronous Pattern. Шаблон IAsyncResult использует методы BeginXXX и EndXXX, использует экземпляры IAsyncResult, использует делегаты для обратных вызовов и поддерживает ожидание завершения. Шаблон, основанный на событиях, использует методы XXXAsync для инициирования асинхронных действий, использует события XXXCompleted вместо обратных вызовов для обработки завершения и (это важно для вашего случая) передает контекст, специфичный для каждого потока, в каждый обработчик события обратного вызова.

Другими словами, если вы поместите код обратного вызова внутри обработчика события XXXCompleted (например, WebClient.DownloadStringCompleted), то HttpContext.Current будет заполнен правильно.

Если, однако, вы используете метод BeginXXX (например, HttpWebRequest.BeginGetResponse) и обратный вызов делегата, ваш обратный вызов будет выполняться в контексте потока, который не гарантирует наличие подходящего контекста ASP.NET.

Как правило, классы библиотеки .NET Framework используют один шаблон async или другой. Как правило, классы нижнего уровня (например, HttpWebRequest) будут использовать шаблон IAsyncResult, тогда как классы более высокого уровня (например, WebClient) будут использовать шаблон, основанный на событиях. Некоторые нечетные классы (например, автогенерируемые прокси .NET Remoting) будут поддерживать оба шаблона, но это редкость.

Поэтому, если это легко сделать, я бы предложил перейти к WebClient и обработчикам событий вместо HttpWebRequest и делегатов callback. Это должно решить вашу проблему. Если переключение на WebClient слишком сложно, прокомментируйте, и я, вероятно, могу предложить несколько более неясных альтернатив.

+0

Я не уверен, насколько это легко осуществить в моем случае.Я полагаю, что я привязан к шаблону IAsyncResult, по крайней мере, на базовом уровне, потому что это шаблон, поддерживаемый AddOnPreRequestHandlerExecuteAsync. И, поскольку у меня есть вещи, работающие в настоящее время, просто сохраняя состояние в переменной, я бы предпочел не смущаться с ним. – aepheus

Смежные вопросы