TaskFactory.FromAsync with BeginGetRequestStream / EndGetRequestStream freezes

I have a method that hangs when declaring a responseObject using Task.Factory.FromAsync ()

 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; } 

It works fine if I manually run Begin / End methods, for example:

  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); 

However, in this case, ReadToEndAsync () is run in a separate thread, and I want the method to return a result, which is not possible since the method returns before the BeginGetResponse callback completes.

At this moment, I think I'm doing this terribly wrong, and this is completely wrong, so any help would be greatly appreciated.

+3
source share
1 answer

First of all: Do not use ".Result" in asynchronous methods. This will block the thread that runs your method. Use "wait" instead, so the thread returns to your method when it gets the result.

The problem with your code is that you open the request stream but never close it. So, when should he finish your request and send it? It always expects more input until the request is timed out. Also, you did not specify the type of content and the length of the content.

 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; } 
+10
source

All Articles