HttpClient と using
C# の REST クライアントといえば HttpClient
。コイツは IDisposable
の実装なので、例えばこんな感じで using
したくなる。
public class MyClient { public async Task<string> Get(string url) { using(var client = new HttpClient()) { var response = await client.GetAsync(url); switch(response.StatusCode) { // ステータスで処理分けたり } return await response.Content.ReadAsStringAsync(); } } }
しかし…… HttpClient
は Dispose
されてもコネクションが残ってしまうようだ。そしたら using
はバッドプラクティスだ。
http://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
スレッドセーフらしいので、こんな実装で回避できる。
public class MyClient { private static readonly HttpClient _client = new HttpClient(); public async Task<string> Get(string url) { var response = await _client.GetAsync(url); // 中略 return await response.Content.ReadAsStringAsync(); } }
もう一歩進むと、どうやらコネクションプールの管理は HttpClientHandler
がやってるらしい。コイツを static readonly
にして、HttpClient
のコンストラクタに渡せば、堂々と using
できる。第2引数は、HttpClient
が Dispose
されたときに HttpClientHandler
も一緒に Dispose
するかどうか。使いまわすなら false
。
public class MyClient { private static readonly HttpClientHandler _handler = new HttpClientHandler(); public async Task<string> Get(string url) { using(var client = new HttpClient(_handler, false) { var response = await client.GetAsync(url); // 中略 return await response.Content.ReadAsStringAsync(); } } }
非同期周りもハマりやすい HttpClient
、なかなか曲者だ。