2015-03-31 51 views
5

我有一個Windows通用項目與多個API調用。 一種方法拒絕工作eventhought我的其他調用工作完全是這樣的。 我試過using關鍵字認爲它可以解決問題。HttpClient上ObjectDisposedException

功能:

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() 
+1

你爲什麼要用'ContinueWith'混合'await'? – 2015-03-31 13:36:09

+0

你爲什麼使用'ContinueWith'?處理異步/等待時,不需要使用'ContinueWith'。 – 2015-03-31 13:36:32

回答

8

ObjectDisposedException被拋出,因爲你在處理之前的HttpRequestMessageHttpClientreq.Content.ReadAsStringAsync()完成。

請注意,req.Content.ReadAsStringAsync()是一種異步方法。在處理HttpClient之前,您需要等待它完成。

此外,你似乎要撥打ReadAsStringAsyncreq.Content,應該不是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; 
} 

幾乎沒有理由在處理異步/等待時使用ContinueWith。所有這些都是由編譯器爲你完成的。

+0

好的謝謝你的提示,但錯誤現在拋出後var result = ... 無法訪問處置的對象。 對象名稱:'System.Net.Http.StringContent'。 – tim 2015-03-31 13:49:30

+0

@SeaSharp現在有什麼例外?發佈堆棧跟蹤和更新後的代碼。 – 2015-03-31 13:50:43

+0

完成。感謝您的幫助。 – tim 2015-03-31 13:56:14

4

您正在訪問請求內容,而不是響應。

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(); 
+0

太晚了:) – tim 2015-03-31 14:10:06

4

實際原因ObjectDisposedException拋出是因爲HttpClient完成的請求後,立即部署了Content。看看docs

所以,如果你需要閱讀Request的內容,例如在測試中,請確保調用前SendAsync閱讀它

+0

我也遇到了這個問題。如果您嘗試重試發送兩次相同的「內容」(在超時或類似情況之後),您將得到一個ObjectDisposedException 有關信息,它看起來像已在參考源中修復: https://github.com/ dotnet/corefx/blob/master/src/System.Net.Http/src/System/Net/Http/HttpClient.cs#L517 (雖然我仍然看到使用System.Net.Http的版本= 4.0.0.0) – 2017-06-05 14:27:45