21

非同期の httpwebrequest の応答を取得する簡単な方法があるかどうか疑問に思っています。

私はすでにこの質問をここで見ましたが、私がやろうとしているのは、応答 (通常は json または xml) を文字列の形式で別のメソッドに返し、そこでそれを解析/処理することです。

いくつかのコードを次に示します。

すべてのパラメーターが渡され、メソッドが使用する共有ローカル変数がないため、これら 2 つの静的メソッドはスレッドセーフだと思いますか?

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 を使用してこれらをラップし、最終的な結果にアクセスしやすくすることができます。たとえば、1 つのオプションは次のようになります。コンテンツ文字列が利用可能になるまで Main メソッドがブロックされていることに注意してください。

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を使用している場合は、.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() を使用するには、「非同期」でもある新しいメソッドを作成します。GetWebPage() メソッドで「await」を使用する必要があるため、非同期が必要です。

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

Web ページの 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 に答える