5

我有一个严重依赖网络服务的网络应用程序。服务的所有内容都是异步完成的,并且使用 AddOnPreRequestHandlerExecuteAsync。无论如何,我的大多数调用都可以正常工作,但有些调用从他们的异步服务调用返回以在 endprerequest 中找到一个空的 HttpContext.Current.Response/Request 对象,这当然会在我尝试使用其中任何一个时出错。两个对象(响应和请求在失败调用的 beginprerequest 上可用/不为空,并在其他调用的 endprerequest 中工作)。

任何人都遇到过类似的情况,或者猜测可能是什么问题?

更新:似乎找到了解决方案,如果我在 Init 上为 HttpApplication 创建一个变量(这一切都发生在 HttpModule 中),则可以从该变量访问 HttpContext。

更新:在开始函数上传递 HttpApplication 或 HttpContext.Current 有同样的问题。当作为异步调用的“状态”的一部分传递时,它们在 end 函数中最终为 null,即使它们在 begin 函数中有效。

更新:我添加了一些日志记录,发现我正在进行的异步调用正确返回,结果在那里,回调函数被正确调用。

4

2 回答 2

5

我怀疑我知道你遇到的问题。几乎可以肯定,答案是用 替换HttpWebRequestWebClient并使用 的 *Async 方法WebClient

下面是详细的解释:有两种完全不同的异步编程模型:IAsyncResult 异步模式基于事件的异步模式。IAsyncResult 模式使用BeginXXXEndXXX方法,使用 IAsyncResult 实例,使用委托进行回调,并支持等待完成。基于事件的模式使用 XXXAsync 方法来启动异步操作,使用XXXCompleted事件而不是回调来处理完成,并且(这对您的情况很重要)将特定于线程的上下文传输到每个回调事件处理程序中。

换句话说,如果您将回调代码放入 XXXCompleted 事件处理程序(如WebClient.DownloadStringCompleted),那么 HttpContext.Current 将被正确填充。

但是,如果您使用 BeginXXX 方法(如HttpWebRequest.BeginGetResponse)和委托回调,则您的回调将在不保证附加正确的 ASP.NET 上下文的线程上下文中执行。

通常,.NET Framework 库类要么使用一种异步模式,要么使用另一种。通常,较低级别的类(例如HttpWebRequest)将使用 IAsyncResult 模式,而较高级别的类(例如WebClient)将使用基于事件的模式。一些古怪的类(例如自动生成的 .NET Remoting 代理)将支持这两种模式,但这种情况很少见。

因此,如果它很容易做到,我建议转移到 WebClient 和事件处理程序而不是 HttpWebRequest 和回调委托。这应该可以解决您的问题。如果切换到 WebClient 太难,请发表评论,我可能会建议一些更晦涩的替代方案。

于 2009-12-27T01:33:04.497 回答
0

似乎找到了解决方案,如果我在 Init 上为 HttpApplication 创建一个变量(这一切都发生在 HttpModule 中),则可以从该变量访问 HttpContext。

于 2010-01-05T16:45:11.557 回答