【问题标题】:Getting the Response of a Asynchronous HttpWebRequest获取异步 HttpWebRequest 的响应
【发布时间】:2012-05-12 15:37:51
【问题描述】:

我想知道是否有一种简单的方法来获取异步 httpwebrequest 的响应。

我已经看到了这个问题here,但我所做的只是将响应(通常是 json 或 xml)以字符串的形式返回到另一个方法,然后我可以在其中解析它/相应地处理它.

这里有一些代码:

我在这里有这两个静态方法,我认为它们是线程安全的,因为所有参数都被传入并且这些方法没有使用共享的局部变量?

public static void MakeAsyncRequest(string url, string contentType)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.ContentType = contentType;
    request.Method = WebRequestMethods.Http.Get;
    request.Timeout = 20000;
    request.Proxy = null;

    request.BeginGetResponse(new AsyncCallback(ReadCallback), request);
}

private static void ReadCallback(IAsyncResult asyncResult)
{
    HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
    try
    {
        using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult))
        {
            Stream responseStream = response.GetResponseStream();
            using (StreamReader sr = new StreamReader(responseStream))
            {
                //Need to return this response 
                string strContent = sr.ReadToEnd();
            }
       }
       manualResetEvent.Set();
    }
    catch (Exception ex)
    {
        throw ex;
   }
}

【问题讨论】:

  • 我删除了多余的 manualResetEvent.Set(); 后,您发布的代码运行良好- 你遇到了什么问题?
  • @JamesManning 嗨,是的,这是一个错字,我正在寻找一种更简单的方法来获得结果。您提供的 (Task) 完全符合要求。我刚刚从同步请求中跳了出来,似乎还有很多事情要做。谢谢

标签: c# asynchronous httpwebrequest httpwebresponse


【解决方案1】:

假设问题是您很难访问返回的内容,如果可以使用,最简单的方法可能是使用 async/await。如果您使用的是 .NET 4.5,最好切换到 HttpClient,因为它是“本机”异步的。

使用 .NET 4 和 C# 4,您仍然可以使用 Task 来包装它们,并使其更容易访问最终结果。例如,一个选项如下。请注意,在内容字符串可用之前,它的 Main 方法会阻塞,但在“真实”场景中,您可能会将任务传递给其他东西,或者将另一个 ContinueWith 串起来或其他任何东西。

void Main()
{
    var task = MakeAsyncRequest("http://www.google.com", "text/html");
    Console.WriteLine ("Got response of {0}", task.Result);
}

// Define other methods and classes here
public static Task<string> MakeAsyncRequest(string url, string contentType)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.ContentType = contentType;
    request.Method = WebRequestMethods.Http.Get;
    request.Timeout = 20000;
    request.Proxy = null;

    Task<WebResponse> task = Task.Factory.FromAsync(
        request.BeginGetResponse,
        asyncResult => request.EndGetResponse(asyncResult),
        (object)null);

    return task.ContinueWith(t => ReadStreamFromResponse(t.Result));
}

private static string ReadStreamFromResponse(WebResponse response)
{
    using (Stream responseStream = response.GetResponseStream())
    using (StreamReader sr = new StreamReader(responseStream))
    {
        //Need to return this response 
        string strContent = sr.ReadToEnd();
        return strContent;
    }
}

【讨论】:

  • 再次感谢您的回答和时间。
  • 一个简单的问题,当访问 MakeAsyncRequest() 方法的 Result 属性时,我如何确保在我尝试使用响应时始终完成结果。
  • Result 属性将一直阻塞,直到它尚未完成。
  • 好的,所以请求将异步发生,只有流的读取将被阻止。
  • @geepie - 正确,无论哪个线程访问 Result 属性(在它准备好之前)都会阻塞,直到任务完成(并且结果将返回)或失败(它会抛出异常)
【解决方案2】:

“如果您使用的是 .Net 4.5,最好切换到 HttpClient,因为它是‘本机’async。” - James Manning 的绝对正确答案。

这个问题是大约 2 年前提出的。现在我们有了 .Net Framework 4.5,它提供了强大的异步方法。使用HttpClient。考虑以下代码:

 async Task<string> HttpGetAsync(string URI)
    {
        try
        {
            HttpClient hc = new HttpClient();
            Task<Stream> result = hc.GetStreamAsync(URI);

            Stream vs = await result;
            StreamReader am = new StreamReader(vs);

            return await am.ReadToEndAsync();
        }
        catch (WebException ex)
        {
            switch (ex.Status)
            {
                case WebExceptionStatus.NameResolutionFailure:
                    MessageBox.Show("domain_not_found", "ERROR",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                break;
                    //Catch other exceptions here
            }
        }
    }

要使用 HttpGetAsync(),请创建一个“异步”的新方法。 async 是必需的,因为我们需要在 GetWebPage() 方法中使用“await”:

async void GetWebPage(string URI)
        {
            string html = await HttpGetAsync(URI);
            //Do other operations with html code
        }

现在,如果您想异步获取网页 HTML 源代码,只需调用 GetWebPage("web-address...")。即使Stream 读取也是异步的。

注意:要使用HttpClient .Net Framework 4.5 是必需的。您还需要在您的项目中添加System.Net.Http 引用并添加“using System.Net.Http”以便于访问。

如需进一步了解此方法的工作原理,请访问:http://msdn.microsoft.com/en-us/library/hh191443(v=vs.110).aspx

使用异步:Async in 4.5: Worth the Await

【讨论】:

    【解决方案3】:

    一旦你去异步,你就再也回不去了。从那里你只能真正访问异步的回调。您可以提高它的复杂性并执行一些线程和等待句柄,但这可能是一项相当痛苦的工作。

    从技术上讲,你也可以在需要等待结果的时候让线程休眠,但我不建议这样做,你还不如在那个时候做一个普通的http请求。

    在 C# 5 中,它们具有 async/await 命令,可以更轻松地获取对主线程的异步调用结果。

    【讨论】:

    • 线程是我必须解决的问题。感谢您的意见。
    【解决方案4】:
    public static async Task<byte[]> GetBytesAsync(string url) {
        var request = (HttpWebRequest)WebRequest.Create(url);
        using (var response = await request.GetResponseAsync())
        using (var content = new MemoryStream())
        using (var responseStream = response.GetResponseStream()) {
            await responseStream.CopyToAsync(content);
            return content.ToArray();
        }
    }
    
    public static async Task<string> GetStringAsync(string url) {
        var bytes = await GetBytesAsync(url);
        return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-28
      • 2021-11-18
      相关资源
      最近更新 更多