2013-08-13 31 views
6

Tôi cần làm cho mã sau không đồng bộ và có thể chờ được.Làm thế nào để làm cho WebRequest bình thường không đồng bộ và chờ đợi?

Tôi cần nhận nhiều dữ liệu từ máy chủ web và sau đó dữ liệu này sẽ được sử dụng để điền trang xaml vào ứng dụng của tôi.

Vì vậy, tôi cần phương thức DefLogin() để chờ.

Có thể không?

public void DefLogin() 
    { 
     postData = "My Data To Post"; 
     var url = new Uri("Url To Post to", UriKind.Absolute); 
     webRequest = WebRequest.Create(url); 
     webRequest.Method = "POST"; 
     webRequest.ContentType = "text/xml"; 
     webRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), webRequest); 
    } 

    public void GetRequestStreamCallback(IAsyncResult asynchronousResult) 
    { 
     webRequest = (HttpWebRequest)asynchronousResult.AsyncState; 
     Stream postStream = webRequest.EndGetRequestStream(asynchronousResult); 
     byte[] byteArray = Encoding.UTF8.GetBytes(postData); 
     postStream.Write(byteArray, 0, byteArray.Length); 
     postStream.Close(); 
     Debug.WriteLine("Start BEGINGetResponse"); 
     webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest); 
    } 

    public void GetResponseCallback(IAsyncResult asynchronousResult) 
    { 
     try 
     { 
      HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState; 
      HttpWebResponse response; 
      response = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult); 
      Stream streamResponse = response.GetResponseStream(); 
      StreamReader streamReader = new StreamReader(streamResponse); 
      string Response = streamReader.ReadToEnd(); 
      streamResponse.Close(); 
      streamReader.Close(); 
      response.Close(); 
      if (Response == "") 
      { 
       //show some error msg to the user   
       Debug.WriteLine("ERROR"); 

      } 
      else 
      { 
       //Your response will be available in "Response" 
       Debug.WriteLine(Response); 
      } 
     } 
     catch (WebException) 
     { 
      //error  
     } 
    } 

Tôi đã thấy câu hỏi này trên StackOverflow: Converting ordinary Http Post web request with Async and Await, nhưng tôi không thể hiểu câu trả lời đúng cách.

Bạn có thể giúp ai không? Tôi sẽ rất biết ơn!

Trả lời

13

Bạn có thể sử dụng TaskFactory.FromAsync để convert APM to TAP, làm cho rất nhiều phương pháp khuyến nông nhỏ như thế này:

public static Task<Stream> GetRequestStreamAsync(this WebRequest request) 
{ 
    return TaskFactory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, null); 
} 

và làm tương tự cho WebRequest.GetResponse và (nếu cần thiết) Stream.Write, Stream.Flush vv

Sau đó, bạn có thể viết logic thực tế của mình bằng cách sử dụng asyncawait mà không có bất kỳ cuộc gọi lại nào:

public async Task DefLoginAsync() 
{ 
    postData = "My Data To Post"; 
    var url = new Uri("Url To Post to", UriKind.Absolute); 
    webRequest = WebRequest.Create(url); 
    webRequest.Method = "POST"; 
    webRequest.ContentType = "text/xml"; 
    using (Stream postStream = await webRequest.GetRequestStreamAsync()) 
    { 
     byte[] byteArray = Encoding.UTF8.GetBytes(postData); 
     await postStream.WriteAsync(byteArray, 0, byteArray.Length); 
     await postStream.FlushAsync(); 
    } 
    try 
    { 
     string Response; 
     using (var response = (HttpWebResponse)await webRequest.GetResponseAsync()); 
     using (Stream streamResponse = response.GetResponseStream()) 
     using (StreamReader streamReader = new StreamReader(streamResponse)) 
     { 
      Response = await streamReader.ReadToEndAsync(); 
     } 
     if (Response == "") 
     { 
      //show some error msg to the user   
      Debug.WriteLine("ERROR"); 

     } 
     else 
     { 
      //Your response will be available in "Response" 
      Debug.WriteLine(Response); 
     } 
    } 
    catch (WebException) 
    { 
     //error  
    } 
} 
+2

Câu trả lời tuyệt vời. Điều này thực sự xứng đáng được tín dụng nhiều hơn. Theo kinh nghiệm của tôi, các phương thức mở rộng sẽ giống như "trả lại Task .Factory.FromAsync (etc ...)", nếu không bạn sẽ gặp phải lỗi "Cuộc gọi không rõ ràng". Cũng đừng bỏ qua việc sử dụng(): chúng rất quan trọng trong việc đảm bảo luồng của bạn được đóng trước khi EndGet ___(). –

Các vấn đề liên quan