I have a method like this, that hangs when declaring 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 the Begin/End methods, like this:
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 that case, ReadToEndAsync() is run on a separate thread, and I want the method to return the result, which isn't possible since the method returns before the BeginGetResponse callback is finished.
At this point I think I am doing this horribly wrong and going about this completely the wrong way, so any help would be much appreciated.
First of all: Don't use ".Result" in async methods. This will block the thread that is running your method. Use "await" instead, so the thread jumps back to your method when the result is acquired.
The problem with your code is that you open a request stream, but you never close it. So when should it expect to finish your request and send it? It'll always expect more input to come, until the request runs in a timeout. Also you have not set a content-type and content-length.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With