异步 HttpWebRequest 和 null HttpContext.Current.Response/Request 对象
我有一个严重依赖网络服务的网络应用程序。服务的所有操作都是通过 AddOnPreRequestHandlerExecuteAsync 异步完成的。无论如何,我的大多数调用都工作得很好,但有些调用从异步服务调用中返回,以在 endprerequest 中找到 null HttpContext.Current.Response/Request 对象,这当然会在我尝试使用其中一个时立即出错。两个对象(响应和请求在失败调用的开始预请求中可用/不为空,并在其他调用的结束预请求中工作)。
有人遇到过类似的情况,或者猜测可能是什么问题吗?
更新:似乎找到了解决方案,如果我在 Init 上为 HttpApplication 创建一个变量(这一切都发生在 HttpModule 中),则可以从该变量访问 HttpContext。
更新:在开始函数上传递 HttpApplication 或 HttpContext.Current 也有同样的问题。当作为异步调用的“状态”的一部分传递时,它们在结束函数中最终为 null,即使它们在开始函数中有效。
更新:我添加了一些日志记录,发现我正在进行的异步调用正确返回,结果在那里,回调函数被正确调用。
I have a web application the relies heavily on web services. Everything with the services is done asynchronously and with AddOnPreRequestHandlerExecuteAsync. Anyhow, most of my calls work just fine, but some are returning from their asynchronous service calls to find a null HttpContext.Current.Response/Request object in the endprerequest, which of course errors the instant I try to use either. Both objects (Response and Request are available/not null on beginprerequest of failing calls and work in the endprerequest of other calls).
Anyone run into similar, or have a guess as to what might be the problem?
Update: Seem to have found a solution, if I create a variable for the HttpApplication on Init(of the HttpModule this all occurs in) the HttpContext can be accessed from that variable.
Update: Passing either HttpApplication or HttpContext.Current on the begin function has the same issue. When passed as part of the "State" of the asynchronous call, they end up null in the end function, even though they are valid in the begin function.
Update: I've added some logging and found that the Asynchronous call I am making is returning correctly, the results are there, the callback function is invoked properly.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
似乎找到了解决方案,如果我在 Init 上为 HttpApplication 创建一个变量(这一切都发生在 HttpModule 中),则可以从该变量访问 HttpContext。
Seem to have found a solution, if I create a variable for the HttpApplication on Init(of the HttpModule this all occurs in) the HttpContext can be accessed from that variable.
我怀疑我知道你遇到的问题。几乎可以肯定,答案是用
WebClient
替换HttpWebRequest
的使用,并使用WebClient
的 *Async 方法。这是详细的解释:有两种完全不同的异步编程模型: IAsyncResult 异步模式< /a> 和基于事件的异步模式。 IAsyncResult 模式使用
BeginXXX
和EndXXX
方法,使用 IAsyncResult 实例,使用委托进行回调,并支持等待完成。基于事件的模式使用 XXXAsync 方法来启动异步操作,使用 XXXCompleted 事件而不是回调来处理完成,并且(这对您的情况很重要)将线程特定的上下文传输到每个回调事件处理程序中。换句话说,如果您将回调代码放入 XXXCompleted 事件处理程序中(例如
WebClient.DownloadStringCompleted
),然后 HttpContext.Current 将被正确填充。但是,如果您使用 BeginXXX 方法(例如
HttpWebRequest.BeginGetResponse
)和委托回调,您的回调将在不保证附加正确的 ASP.NET 上下文的线程上下文中执行。通常,.NET Framework 库类使用一种异步模式或另一种。通常,较低级别的类(例如
HttpWebRequest
)将使用IAsyncResult 模式,而较高级别的类(例如WebClient
)将使用基于事件的模式。一些奇怪的类(例如自动生成的.NET Remoting 代理)将支持这两种模式,但这种情况很少见。因此,如果很容易做到,我建议转向 WebClient 和事件处理程序,而不是 HttpWebRequest 和回调委托。这应该可以解决你的问题。如果切换到 WebClient 太难,请发表评论,我可能会建议一些更晦涩的替代方案。
I suspect I know the problem you're running into. The answer, almost certainly, is to replace usage of
HttpWebRequest
withWebClient
, and to use the *Async methods ofWebClient
.Here's the long explanation: there are two totally different Async programming models: the IAsyncResult Async Pattern and the Event-based Asynchronous Pattern. The IAsyncResult pattern uses
BeginXXX
andEndXXX
methods, uses IAsyncResult instances, uses delegates for callbacks, and supports waiting for completion. The Event-based pattern uses XXXAsync methods to initiate async actions, usesXXXCompleted
events instead of callbacks to handle completion, and (this is important to your case) transfers thread-specific context into every callback event handler.In other words, if you put your callback code inside a XXXCompleted event handler (like
WebClient.DownloadStringCompleted
), then HttpContext.Current will be populated correctly.If, however, you use a BeginXXX method (like
HttpWebRequest.BeginGetResponse
) and a delegate callback, your callback will be executed in the context of a thread that does not guarantee to have the right ASP.NET context attached.Generally, .NET Framework library classes either use one async pattern or the other. Typically, the lower-level classes (e.g.
HttpWebRequest
) will use the IAsyncResult pattern, while the higher-level classes (e.g.WebClient
) will use the event-based pattern. Some oddball classes (e.g. auto-generated .NET Remoting proxies) will support both patterns, but that's a rarity.So if it's easy to do, I'd suggest moving to WebClient and event handlers instead of HttpWebRequest and callback delegates. This should solve your problem. If switching to WebClient is too hard, comment and I can probably suggest some more obscure alternatives.