web-dev-qa-db-ja.com

同期接続にHttpClientを使用する理由

私はAPIと対話するためのクラスライブラリを構築しています。 APIを呼び出してXML応答を処理する必要があります。非同期接続にHttpClientを使用することの利点はわかりますが、私がやっていることは純粋に同期なので、HttpWebRequestを使用することに比べて大きな利点はありません。

誰もが光を当てることができれば私はそれを高く評価するでしょう。私はそれを目的として新しい技術を使用しているのではありません。

160
Ketchup

しかし私がやっていることは純粋に同期です

同期リクエストにHttpClientを使用することもできます。

using (var client = new HttpClient())
{
    var response = client.GetAsync("http://google.com").Result;

    if (response.IsSuccessStatusCode)
    {
        var responseContent = response.Content; 

        // by calling .Result you are synchronously reading the result
        string responseString = responseContent.ReadAsStringAsync().Result;

        Console.WriteLine(responseString);
    }
}

なぜWebRequest上でHttpClientを使用すべきなのかという点に関しては、HttpClientが新たなブロックとなり、古いクライアントに対する改善が含まれる可能性があります。

326
Darin Dimitrov

Donny V.の回答とJoshの回答をもう一度繰り返します。

「非同期バージョンを使用しない唯一の理由は、非同期サポートが組み込まれていない古いバージョンの.NETをサポートしようとしている場合です。」

(私が評判を得たならば、そして投票してください。)

HttpWebRequestがステータスコード> = = 400の例外をスローしたことに感謝しました。これらの問題を回避するには、すぐに例外をキャッチし、それらを例外以外の応答メカニズムにマップする必要があります。あなたのコードでは...退屈で、退屈で、エラー自体が起こりがちです。それがデータベースと通信しているか、オーダーメイドのWebプロキシを実装しているかにかかわらず、Httpドライバがアプリケーションコードに返されたものを伝え、振る舞い方を決めるのはあなたに任せることが「ほぼ」常に望まれます。

それ故、HttpClientが好ましい。

23
trev

私がHttpClientを使用する主な理由の1つは、404がURLに返されたときに例外がスローされないためです。

17
Donny V.

もしあなたがクラスライブラリを構築しているのなら、おそらくあなたのライブラリのユーザはあなたのライブラリを非同期的に使いたいと思うでしょう。それこそが最大の理由だと思います。

また、あなたの図書館がどのように使われるのかもわかりません。おそらく、ユーザーは大量の要求を処理し、非同期でそれを実行することで、より速くより効率的に実行できるようになります。

それが簡単にできるのであれば、フローを非同期にしようとしているときにライブラリのユーザーに負担をかけないようにしてください。

非同期バージョンを使用しない唯一の理由は、非同期サポートが組み込まれていない古いバージョンの.NETをサポートしようとした場合です。

6
Josh Smeaton

私の場合、受け入れられた答えはうまくいきませんでした。非同期アクションのないMVCアプリケーションからAPIを呼び出していました。

これが私がどうやってそれを機能させることができたかです:

private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);
public static T RunSync<T>(Func<Task<T>> func)
    {           
        CultureInfo cultureUi = CultureInfo.CurrentUICulture;
        CultureInfo culture = CultureInfo.CurrentCulture;
        return _myTaskFactory.StartNew<Task<T>>(delegate
        {
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = cultureUi;
            return func();
        }).Unwrap<T>().GetAwaiter().GetResult();
    }

それから私はこのようにそれを呼びました:

Helper.RunSync(new Func<Task<ReturnTypeGoesHere>>(async () => await AsyncCallGoesHere(myparameter)));
6
Darkonekt
public static class AsyncHelper  
{
    private static readonly TaskFactory _taskFactory = new
        TaskFactory(CancellationToken.None,
                    TaskCreationOptions.None,
                    TaskContinuationOptions.None,
                    TaskScheduler.Default);

    public static TResult RunSync<TResult>(Func<Task<TResult>> func)
        => _taskFactory
            .StartNew(func)
            .Unwrap()
            .GetAwaiter()
            .GetResult();

    public static void RunSync(Func<Task> func)
        => _taskFactory
            .StartNew(func)
            .Unwrap()
            .GetAwaiter()
            .GetResult();
}

それから

AsyncHelper.RunSync(() => DoAsyncStuff());

そのクラスを使用する場合は、非同期メソッドをパラメータとして渡すことで、安全な方法で同期メソッドから非同期メソッドを呼び出すことができます。

それはここで説明されています: https://cpratt.co/async-tips-tricks/

0