21

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

我已经在这里看到了这个问题,但我想做的只是将响应(通常是 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;
   }
}
4

4 回答 4

44

假设问题是您很难获得返回的内容,那么最简单的路径可能是使用 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;
    }
}
于 2012-05-12T15:58:16.957 回答
8

HttpClient“如果你使用的是 .Net 4.5,那就更好了,因为它是‘本机’的async。” - 詹姆斯曼宁绝对正确的答案。

这个问题是大约 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

使用异步:4.5 中的异步:值得等待

于 2014-09-01T19:35:51.873 回答
2

一旦你去异步,你就再也回不去了。从那里你只能真正访问异步的回调。你可以增加它的复杂性并做一些线程和等待句柄,但这可能是一个相当痛苦的努力。

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

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

于 2012-05-12T15:42:18.327 回答
0
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);
}
于 2018-03-11T20:27:20.063 回答