2012-12-31 27 views
3

我有這樣的方法,使用Task.Factory.FromAsync聲明responseObject時掛起()TaskFactory.FromAsync與BeginGetRequestStream/EndGetRequestStream掛起

private async Task<string> post(string url, string postdata) 
     { 
      var request = WebRequest.Create(new Uri(url)) as HttpWebRequest; 
      request.Method = "POST"; 

      // this works 
      Task<Stream> requestStream = Task<Stream>.Factory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, request); 
      var sw = new StreamWriter(requestStream.Result); 
      byte[] data = Encoding.UTF8.GetBytes(postdata); 
      await requestStream.Result.WriteAsync(data, 0, data.Length); 

      // this hangs 
      Task<WebResponse> responseObject = Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, request); // Hangs here 
      // Doesn't get to here 
      var responseStream = responseObject.Result.GetResponseStream(); 
      var sr = new StreamReader(responseStream); 
      string received = await sr.ReadToEndAsync(); 

      return received; 
} 

,如果我手動運行開始/結束的方法正常工作,像這樣:

 request.BeginGetRequestStream(async ar => 
     { 
      var requestStream = request.EndGetRequestStream(ar); 
      using (var sw = new StreamWriter(requestStream)) 
      { 
       byte[] data = Encoding.UTF8.GetBytes(postdata); 
       await requestStream.WriteAsync(data, 0, data.Length); 
      } 

      request.BeginGetResponse(async a => 
      { 
       HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(a); 
       var responseStream = response.GetResponseStream(); 
       using (var sr = new StreamReader(responseStream)) 
       { 
        string received = await sr.ReadToEndAsync(); 
       } 

      }, null); 
     }, null); 

然而,在這種情況下,ReadToEndAsync()是在一個單獨的線程運行,我想該方法返回的結果,這是不可能的,因爲BeginGetResponse回調之前該方法返回完成。

在這一點上,我想我正在做這個可怕的錯誤,並完全錯誤的方式去做,所以任何幫助將不勝感激。

回答

10

首先:不要在異步方法中使用「.Result」。這將阻止正在運行您的方法的線程。使用「await」來代替,所以線程在獲取結果時跳回到你的方法。

你的代碼存在的問題是你打開了一個請求流,但你永遠不會關閉它。那麼它應該什麼時候完成你的請求併發送它?它始終需要更多的輸入,直到請求在超時運行。您還沒有設置內容類型和內容長度。

private async Task<string> post(string url, string postdata) 
    { 
     var request = WebRequest.Create(new Uri(url)) as HttpWebRequest; 
     request.Method = "POST"; 

     byte[] data = Encoding.UTF8.GetBytes(postdata); 
     request.ContentLength = data.Length; 

     using (var requestStream = await Task<Stream>.Factory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, request)) 
     { 
      await requestStream.WriteAsync(data, 0, data.Length); 
     } 


     WebResponse responseObject = await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, request); 
     var responseStream = responseObject.GetResponseStream(); 
     var sr = new StreamReader(responseStream); 
     string received = await sr.ReadToEndAsync(); 

     return received; 
}