APIと対話するためのクラスライブラリを構築しています。APIを呼び出してXML応答を処理する必要があります。HttpClient
非同期接続に使用することの利点はわかりますが、私がしていることは純粋に同期であるため、を使用することよりも大きな利点はありませんHttpWebRequest
。
誰かが光を当てることができれば私はそれを大いに感謝します。私はそれのために新しいテクノロジーを使用するためのものではありません。
APIと対話するためのクラスライブラリを構築しています。APIを呼び出してXML応答を処理する必要があります。HttpClient
非同期接続に使用することの利点はわかりますが、私がしていることは純粋に同期であるため、を使用することよりも大きな利点はありませんHttpWebRequest
。
誰かが光を当てることができれば私はそれを大いに感謝します。私はそれのために新しいテクノロジーを使用するためのものではありません。
回答:
しかし、私がやっていることは純粋に同期です
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);
}
}
なぜHttpClient
オーバーを使用する必要があるかということWebRequest
に関しては、まあ、HttpClient
ブロックの新しい子供であり、古いクライアントに対する改善を含めることができます。
string responseString = Task.Run(() => responseContent.ReadAsStringAsync()).Result;
場合は、代わりに何かを検討する必要があります。
Task.Run
はThreadPoolからタスクを呼び出しますが、これを呼び出して.Result
、これによるすべての利点を殺し、これを呼び出したスレッド.Result
(通常、メインのUIスレッド)をブロックします。
.Result
ような呼び出しはスレッドプールを使い果たし、デッドロックを引き起こす可能性があります。
new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext()
私はドニーV.の回答とジョシュの
「非同期バージョンを使用しない唯一の理由は、非同期サポートが組み込まれていない古いバージョンの.NETをサポートしようとした場合です。」
(そして私が評判を持っている場合は賛成票を投じます。)
前回のことは思い出せませんが、HttpWebRequestがステータスコード> = 400の例外をスローしたという事実に感謝しました。これらの問題を回避するには、例外をすぐにキャッチし、例外以外の応答メカニズムにマッピングする必要がありますあなたのコードでは...退屈で退屈でエラーが発生しやすいです。データベースと通信する場合でも、カスタムのWebプロキシを実装する場合でも、Httpドライバーがアプリケーションコードに返されたものを通知し、動作方法を決定するのはユーザーに任せるのが常に「ほぼ」望ましいことです。
したがって、HttpClientが推奨されます。
HttpClient
それ自体がラッパーであることに驚きましたHttpWebRequest
(実際、内部的にこれらのWebException
オブジェクトをキャッチし、変換をHttpResponseMessage
行います)。新しいクライアントを完全にゼロから構築する方が簡単だと思いました。
クラスライブラリを構築している場合、おそらくライブラリのユーザーはライブラリを非同期で使用したいと思うでしょう。それが最大の理由だと思います。
また、ライブラリの使用方法もわかりません。おそらく、ユーザーは大量のリクエストを処理し、非同期で処理することで、より高速かつ効率的に実行できます。
簡単にできる場合は、ライブラリのユーザーがフローを非同期にしようとするときに、ユーザーの負担を軽減できるようにしてください。
非同期バージョンを使用しない唯一の理由は、非同期サポートが組み込まれていない古いバージョンの.NETをサポートしようとした場合です。
私の場合、受け入れられた答えはうまくいきませんでした。非同期アクションのない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)));
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/
すべての回答はHttpClient
、質問に実際に回答するのではなく、同期して使用することに焦点を当てているようです。
HttpClient
これは単純な要求/応答ハンドラ以上のものなので、さまざまなネットワークのいくつかの特殊性に対処できます。つまり、私の場合、ネゴシエーションを必要とするNTLMプロキシで作業し、認証のためにクライアントとプロキシサーバー間でトークンと資格情報を含む複数の要求/応答を送信します。HttpClient
(を使用HttpClientHandler
)には、1つのメソッド呼び出しでプロキシを超えてリソースを返す処理メカニズムが組み込まれているようです。