ASP.NET HttpWebRequest冻结其他页面

时间:2013-12-29 09:37:10

标签: c# asp.net httpwebrequest

如果我在页面A中创建HttpWebRequest GetResponse(),当我加载其他页面时,它将冻结,直到页面A完全加载。

代码:

    HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

    request.Method = method;

    request.Accept = "text/javascript, text/html, application/xml, text/xml, */*";
    request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
    request.Host = "steamcommunity.com";
    request.UserAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47 Safari/536.11";

    // Get the response
    return request.GetResponse() as HttpWebResponse;

如何在不冻结其他页面的情况下使其异步?

1 个答案:

答案 0 :(得分:2)

一点介绍:

HTTP协议是请求/响应协议。这意味着客户端发送请求,服务器执行一些处理并返回响应。

如果在处理请求的过程中服务器需要向远程资源发出另一个请求并将此请求的结果用于其响应,那么您无需等待。

据说你可以利用asynchronous pages和I / O完成端口来优化它。这基本上允许在执行远程HTTP请求期间释放工作线程。

不要误以为这会使响应变得更快。如果远程服务器很慢,它不会危害您的工作线程。这意味着您的应用程序将能够为其他请求提供服务。

为了实现这一点,您可以使用HttpWebRequest的BeginGetResponse/EndGetResponse方法。它们允许利用I / O完成端口进行异步执行。

在我之前在我的回答中链接的文章中,您将找到如何使您的ASP.NET页面(或者如果您使用处理程序)异步。

第一步是将WebForm标记为异步:

<%@ Page Async="true" ... %>

然后您可以使用AddOnPreRenderCompleteAsync方法注册异步任务:

using System;
using System.IO;
using System.Net;
using System.Web;

public partial class WebForm1 : System.Web.UI.Page
{
    private HttpWebRequest request;

    protected void Page_Load(object sender, EventArgs e)
    {
        this.AddOnPreRenderCompleteAsync(
            new BeginEventHandler(this.BeginAsyncOperation), 
            new EndEventHandler(this.EndAsyncOperation)
        );
    } 

    private IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object state) 
    {
        string url = "http://example.com";
        string method = "GET";

        this.request = (HttpWebRequest)WebRequest.Create(url);
        this.request.Method = method;

        this.request.Accept = "text/javascript, text/html, application/xml, text/xml, */*";
        this.request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
        this.request.Host = "steamcommunity.com";
        this.request.UserAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47 Safari/536.11";

        return this.request.BeginGetResponse(cb, state); 
    } 

    private void EndAsyncOperation(IAsyncResult ar) 
    { 
        using (WebResponse response = this.request.EndGetResponse(ar))
        using (StreamReader reader = new StreamReader(response.GetResponseStream())) 
        { 
            string result = reader.ReadToEnd(); 
            // TODO: do something with the result here => like binding
            // it to some Web Control or displaying it somewhere on the page
        } 
    }
}

作为此方法的替代方法,您可以考虑更快地加载页面,然后向另一个执行远程请求并返回结果的处理程序触发AJAX请求。在这种情况下,初始请求页面将加载更快并且不会被冻结,但是一旦远程请求完成处理,结果将在稍后出现。

但在这两种情况下,我都建议你利用异步页面来避免阻塞你的工作线程,这对你的应用程序来说可能是灾难性的,特别是如果由于某种原因你正在访问的远程服务器很慢。