複数のAPI呼び出しを持つWindowsユニバーサルプロジェクトがあります。他の呼び出しがこのように完全に機能するとしても、1つの方法で機能しません。 using
キーワードを試してみたところ、問題が解決すると思われました。
関数:
public async Task<User> GetNewUser(string user_guid, OAuthTokens OAuth)
{
String userguidJSON = VALIDJSON_BELIEVE_ME;
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", Encrypt(OAuth.Accesstoken));
using (HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, BASE_URL + URL_USERS + "/data"))
{
req.Content = new StringContent(userguidJSON, Encoding.UTF8, "application/json");
await httpClient.SendAsync(req).ContinueWith(respTask =>
{
Debug.WriteLine(req.Content.ReadAsStringAsync()); //Error is thrown ono this line
});
return null;
}
}
}
[〜#〜]編集[〜#〜]
public async Task<User> GetNewUser(string user_guid, OAuthTokens OAuth)
{
String userguidJSON = VALIDJSON_BELIEVE_ME;
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", Encrypt(OAuth.Accesstoken));
using (HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, BASE_URL + URL_USERS + "/data"))
{
req.Content = new StringContent(userguidJSON, Encoding.UTF8, "application/json");
await httpClient.SendAsync(req);
var result = await req.Content.ReadAsStringAsync(); //Cannot access a disposed object. Object name: 'System.Net.Http.StringContent'.
Debug.WriteLine(result);
return null;
}
}
}
スタックトレース
at System.Net.Http.HttpContent.CheckDisposed()
at System.Net.Http.HttpContent.ReadAsStringAsync()
at Roadsmart.Service.RoadsmartService.<GetNewUser>d__2e.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Roadsmart.ViewModel.SettingsPageViewModel.<SetNewProfilePicture>d__1e.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__3(Object state)
at System.Threading.WinRTSynchronizationContext.Invoker.InvokeCore()
ObjectDisposedException
がスローされるのは、req.Content.ReadAsStringAsync()
が完了する前にHttpRequestMessage
とHttpClient
を破棄するためです。
req.Content.ReadAsStringAsync()
は非同期メソッドであることに注意してください。 HttpClient
を破棄する前に、完了するのを待つ必要があります。
また、req.Content
でReadAsStringAsync
を呼び出しているようですが、response.Content
である必要はありませんか?
using (HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, BASE_URL + URL_USERS + "/data"))
{
req.Content = new StringContent(userguidJSON, Encoding.UTF8, "application/json");
var response = await httpClient.SendAsync(req);
var result = await response.Content.ReadAsStringAsync();//await it
Debug.WriteLine(result);
return null;
}
Async/awaitを処理するときにContinueWith
を使用する理由はほとんどありません。これらはすべてコンパイラーによって行われます。
ObjectDisposedException
がスローされる実際の理由は、HttpClient
がリクエストの完了直後にContent
を破棄するためです。 docs をご覧ください。
したがって、テストなどでRequest
の内容を読み取る必要がある場合は、必ずSendAsync
を呼び出す前にbeforeを読んでください。
応答ではなく、要求のコンテンツにアクセスしています。
この
await httpClient.SendAsync(req);
var result = await req.Content.ReadAsStringAsync(); //Cannot access a disposed object. Object name: 'System.Net.Http.StringContent'.
する必要があります
var response = httpClient.SendAsync(req);
var result = await response.Content.ReadAsStringAsync();