I am using the Async CTP library for Windows Phone. Does anyone know how to cancel a pending webrequest?
Request = (HttpWebRequest)WebRequest.Create(url);
Request.Credentials = new NetworkCredential(_settings.Username, _settings.Password);
WebResponse resp;
try
{
resp = await Request.GetResponseAsync();
}
There is no cancellation token (as specified in the ASYNC Ctp tap document).
You could try calling Request.Abort().
Related
I have this method that downloads data from the internet:
public ObservableCollection<Magnetka> ParseJSON() {
ObservableCollection<Models.Magnetka> Markers = new ObservableCollection<Models.Magnetka>();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("(URL)");
request.Headers.Add("Authentication-Token", "(KEY)");
request.Method = "GET";
request.ContentType = "application/json";
CookieContainer cookieContainer = new CookieContainer();
request.CookieContainer = cookieContainer;
var response = request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
......... JSON parsing)
return Markers;
Now I found out this isn't too fast and it freezes the app for two seconds or so, so I need to make it async. However, I call the method like this in another class:
GetMarkers getMarkers = new GetMarkers();
Markers = getMarkers.ParseJSON();
How can I make my method async? I don't understand the concept well and if I make ParseJSON() async Task, I don't know where to put the "await" keyword.
Can anyone help me?
first, mark the method async and use the async version of GetResponse
public async Task<ObservableCollection<Magnetka>> ParseJSON()
{
...
var response = await request.GetResponseAsync();
...
return Markers;
}
then when you call it use the await keyword
Markers = await getMarkers.ParseJSON();
You would change your method to something like this instead:
public async Task<ObservableCollection<Magnetka>> ParseJSON()
{
var markers = new ObservableCollection<Magnetka>();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("(URL)");
request.Headers.Add("Authentication-Token", "(KEY)");
request.Method = "GET";
request.ContentType = "application/json";
CookieContainer cookieContainer = new CookieContainer();
request.CookieContainer = cookieContainer;
using var response = await request.GetResponseAsync().ConfigureAwait(false);
using var responseStream = response.GetResponseStream();
using var streamReader = new StreamReader(responseStream);
var json = await streamReader.ReadToEndAsync().ConfigureAwait(false);
// json parsing
return markers;
}
Firstly, you would mark your method async. This signals the compiler to set up a state machine for this method for continuation. Nothing async happening yet though.
Another thing you need to do is to wrap your return value in a Task, which is similar to a promise in some other languages. Tasks are await-able, which is where the asynchronous stuff is happening.
Switching from using the synchronous methods in WebRequest to use the Async variants and awaiting their results makes your method async.
So from:
request.GetResponse()
To:
await request.GetResponseAsync()
Which returns a awaitable Task<WebResponse>.
The same goes for the stream reader code, you can use its async API too.
A tricky thing by using asynchronous code is that, it kind of forces you to do this all the way up. However, there are exceptions for lifecycle methods and events, where you don't necessarily have to change the signature to return a Task.
Another thing you might notice here. I've added ConfigureAwait(false) at the end of the async method calls. I've done this because out of the box, after returning from an awaited method, the code will try to return to the originating context. This can lead to a couple of issues such as dead-locks if the originating context is the UI Thread. Or, it can lead to bad performance trying to switch between context a lot. Adding ConfigureAwait(false) will just return on the same context the await was run on, which is fine as long as we don't need or expect to return on that context.
As for where you call ParseJson() is probably equally important. Consider deferring it to some lifecycle method or event where you are not doing much else.
This could be OnResume() on Android or ViewWillAppear on iOS. If you are using MVVM, use a Command to encapsulate it.
When i'm sending a http request with my app, the UI of my app freezes while i'm waiting for the http response.
Why is this happening?
async void HttpAction()
{
var request = HttpWebRequest.Create(url);
request.Method = "GET";
request.Timeout = 1500;
await Task.Delay(500);
using (HttpWebResponse reponse = request.GetResponse() as HttpWebResponse)
{
if (reponse.StatusCode == HttpStatusCode.OK)
{
//UI action
reponse.Close();
}
}
Thanks a lot!
You need to await the HttpAction method at the calling point. Go through this Async/Await article first for better understanding of Asynchronous programming.
There should not be any UI action inside Asynchronous Task rather return the result to the calling point and then perform the necessary actions.
async Task<bool> GetHttpAsyncStatus()
{
var request = HttpWebRequest.Create(url);
request.Method = "GET";
request.Timeout = 1500;
using (HttpWebResponse reponse = await request.GetResponseAsync() as HttpWebResponse)
{
if (reponse.StatusCode == HttpStatusCode.OK)
{
// no UI Action, just return the result
reponse.Close();
return true;
}
return false;
}
}
This must be invoked as
bool requestStatus = await GetHttpAsyncStatus();
You need to use AsyncTask and run your http calls in the doInBackground method.
And inside the onPostExecute method, you update the ui. AsyncTask is not terribly involved and will free up the ui thread. I don't have much experience with async but AsyncTask and HttpurlConnection has never failed me on the more tricky stuff.
WebRequest req = WebRequest.Create("[URL here]");
WebResponse rep = req.GetResponse();
I wanted some insights into the relevance of the GetResponse method, it appears to deprecated now.
This other method I hacked together gets the job done.
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(String.Format("http://mywebservicehere/dostuff?url=https://www.website.com"));
request.Method = "GET";
using (var response = (HttpWebResponse) (await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
var encoding = ASCIIEncoding.ASCII;
StreamReader reader = new StreamReader(response.GetResponseStream(), encoding);
}
Wanted to know of any alternative methods others may have used? Thanks for the help!
I wanted some insights into the relevance of the GetResponse method,
it appears to deprecated now.
It is not deprecated, in the .NET for UWP, is is an async method.
WebRequest req = WebRequest.Create("[URL here]");
WebResponse rep = await req.GetResponseAsync();
Wanted to know of any alternative methods others may have used?
Besides the WebRequest class, there are another 2 HttpClient classes in the Windows Runtime Platform you can use to get a http response.
var client1 = new System.Net.Http.HttpClient();
var client2 = new Windows.Web.Http.HttpClient();
The System.Net.Http.HttpClient is in the .NET for UWP.
The Windows.Web.Http.HttpClient is in the Windows Runtime.
I'm trying to use the Azure media services with REST api, in a xamarin shared project on visual studio 2013. This is the code i use to get the access token.
public HttpFactory()
{
string token = GetToken(serviceURI).Result;
//some more methods also async tasks
}
private async Task<string> GetToken(Uri serviceUri)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceURI);
request.Accept = "application/json";
request.Method = "GET";
request.Headers["Host"] = "media.windows.net";
request.Headers["x-ms-version"] = "2.9";
request.Headers["Authorization"] = "Bearer " + token;
var response = (HttpWebResponse) await request.GetResponseAsync();
if (response.StatusCode == HttpStatusCode.MovedPermanently)
{
serviceURI = new Uri(response.Headers["Location"]);
HttpWebRequest req = ( HttpWebRequest)WebRequest.Create(serviceURI);
var res = (HttpWebResponse)await req.GetResponseAsync();
using (Stream responseStream = res.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
string str = reader.ReadToEnd();
// var test = JsonConvert.DeserializeObject(str);
JToken jtoken = JsonConvert.DeserializeObject<JToken>(str);
return jtoken["access_token"].Value<string>();
}
}
}
return "";
}
But when the compiler reaches -
var response = (HttpWebResponse) await request.GetResponseAsync();
it skips the rest of the code, and i never get the response. I know the code is working - because it works just fine without the task, in a async void method.
Anyone knows how to fix this, or am i doing something wrong? I also tried this in vs2015 but its the same.
You have a deadlock over the UI thread.
You're blocking the thread with Task.Result when it is needed to complete the async method which will complete the task that it's waiting on.
That's why you shouldn't block synchronously on asynchronous code. You should await the task returned from GetToken instead:
string token = await GetToken(serviceURI);
If you can't use async in that method, either move that logic to a different method (e.g. OnLoad event handler).
Another solution would be to use ConfigureAwait on the GetResponseAsync task and so the rest of the method wouldn't run on the UI thread, avoiding the deadlock:
var response = (HttpWebResponse) await request.GetResponseAsync().ConfigureAwait(false);
How can I use await with HttpWebRequest in Windows Phone 8 ?
Is there a way to make the IAsyncResult stuff work with await?
private async Task<int> GetCurrentTemperature()
{
GeoCoordinate location = GetLocation();
string url = "http://free.worldweatheronline.com/feed/weather.ashx?q=";
url += location.Latitude.ToString();
url += ",";
url += location.Longitude.ToString();
url += "&format=json&num_of_days=1&key=MYKEY";
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.BeginGetResponse(new AsyncCallback(OnGotWebRequest), webRequest);
}
private void OnGotWebRequest(IAsyncResult asyncResult)
{
HttpWebRequest webRequest = (HttpWebRequest)asyncResult.AsyncState;
var httpResponse = (HttpWebResponse)webRequest.EndGetResponse(asyncResult);
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
string responseText = streamReader.ReadToEnd();
}
}
Thanks!
Use TaskFactory.FromAsync to create a Task<Stream> from the BeginGetRequestStream/EndGetRequestStream methods. Then you can get rid of your OnGotWebRequest completely, and do the same thing for the response.
Note that currently you're calling EndGetResponse when a BeginGetRequestStream call completes, which is inappropriate to start with - you've got to call the EndFoo method to match the BeginFoo you originally called. Did you mean to call BeginGetResponse?
If you install the Microsoft.Bcl.Async package, you get a few async-ready extension methods, including ones for HttpWebRequest.