I have the following piece of code (WPF, Windows Phone 8.1):
HttpClient client = new HttpClient();
var httpResult = client.GetAsync(feed.Url, ct);
string feedData = await httpResult.Result.Content.ReadAsStringAsync();
var sf = new SyndicationFeed();
sf.Load(feedData);
I'm trying to debug this code. However, after the line:
string feedData = await httpResult.Result.Content.ReadAsStringAsync();
debugger seems to let application run on its own and never reaches the next line. Why is that? Am I doing something wrong?
Depending on if you are calling result or wait on the task somewhere upstream, this can result in a deadlock as noted in Stephen Cleary's blog post.
Mitigate this by awaiting the client.GetAsync() and use ConfigureAwait where possible to minimize chances of deadlocks:
HttpClient client = new HttpClient();
var httpResult = await client.GetAsync(feed.Url, ct).ConfigureAwait(false);
string feedData = await httpResult.Content.ReadAsStringAsync().ConfigureAwait(false);
var sf = new SyndicationFeed();
sf.Load(feedData)
Related
It happens on Console and Windows Service apps, haven't tested on Windows Forms or WPF. When stepping thru the code whenever it hits an async call with await, the debug session exits abruptly, can't go further. As a workaround I'm using Task.Run() but changing all the async calls to use Task.Run() syntax during debug, and put it back to "await" syntax for deployment is a hassle.
Here in this method below, the following line is the issue during Debug, it works as expected when deployed.
var response = await httpClient.SendAsync(request);
Work around while debugging is to change the above line to this:
//var response = await httpClient.SendAsync(request);
var task = Task.Run(() => httpClient.SendAsync(request));
task.Wait();
var response = task.Result;
Code:
private static async Task<string> SendRequest()
{
string result = "";
string url = "http://localhost:5119/WeatherForecast";
var URL = new Uri(url);
var method = new HttpMethod("GET");
using (var request = new HttpRequestMessage(method, URL))
{
var response = await httpClient.SendAsync(request);
//var task = Task.Run(() => httpClient.SendAsync(request));
//task.Wait();
//var response = task.Result;
result = await response.Content.ReadAsStringAsync();
}
return result;
}
I was reading the following topic http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
and decided to write a common utility method in my library to do a GET on remote url via HTTPClient
public static async Task<T> GetAsync<T>(HttpGetObject getObject)
{
string baseUrl = getObject.BaseUrl;
string actionUrl = getObject.ActionRelativeUrl;
string acceptType = getObject.AcceptType;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(acceptType));
AddCustomHeadersToHttpClient(client, getObject);
// HTTP GET
HttpResponseMessage httpResponseMessage = await client.GetAsync(actionUrl).ConfigureAwait(false);
if (httpResponseMessage.IsSuccessStatusCode)
{
T response = await httpResponseMessage.Content.ReadAsAsync<T>().ConfigureAwait(false);
return response;
}
else
{
string message = httpResponseMessage.Content.ReadAsStringAsync().Result;
throw new Exception(message);
}
}
return default(T);
}
I know the "await httpResponseMessage.Content.ReadAsAsync().ConfigureAwait(false)" will prevent the deadlock in the above code
First:
My query is for "string message = httpResponseMessage.Content.ReadAsStringAsync().Result" line, will .Result can cause deadlock or not in that line?
Second:
If I call that code from UI like this:
public static object DoGet()
{
// Build getObject
var task = Utility.GetAsync(getObject);
task.Wait();
var response = task.Result;
return response;
}
Will that cause a deadlock?
Please note that I know to avoid all the mess with async-await, all the methods from UI to DAL must be async-await but I am not in position at this moment to change all that structure, my goal at this moment is to call HttpClient library and do a few GET operations.
So my questions is that will the above code can cause a deadlock?
Third:
Is task.Wait(); even needed in the above code?
In the general case, you should assume that yes, calling .Result or .Wait() on anything awaitable is dangerous and can deadlock (unless you are the library issuing the task, and you understand the full context). It is possible that it will work OK in some specific cases, but you should not rely on that behaviour, even if it works today.
I have this code:
using (var client = new HttpClient())
{
var values = new Dictionary<string, string>
{
{"site_id","001"},
{"apikey","abc01201az1024"},
{"trans_id","45364136"},
};
// Get the parameters in the url encoded format
var content = new FormUrlEncodedContent(values);
//Send request
var response = await client.PostAsync(url, content);
DataRoot<Transaction> outPut = null;
if (response.IsSuccessStatusCode)
{
//Get Response
var result = await response.Content.ReadAsStringAsync();
JsonConvert.DeserializeObject<DataRoot<Transaction>>(result);
}
return outPut;
}
In the debug mode at this stage, the code does not produce any response, no error code but stops running:
//Send request
var response = await client.PostAsync(url, content);
there could be a better way but this solved my problem. Call your method from another one using wait:-
public static async Task<string> AuthenticateUser()
{
var t = Task.Run(() => ClassObject.AuthenticateUser("me"));
t.Wait();
Console.WriteLine(t.Result);
Console.ReadLine();
return "ok";
}
Using await like this, can end up in a deadlock.
You can use ConfigureAwait(false) in async methods for preventing such a deadlock.
Update code to:
var response = await client.PostAsync(url, content).ConfigureAwait(false);
This will solve the issue.
Are you sure that it isn't actually returning the response and continuing execution? Because the client.PostAsync() call is awaited execution may continue on a different thread. Therefore, if you're just debugging line by line (via F10 or similar) it may appear that the method never returns; in actuality the entire method has finished execution and your program is running.
You may need to add another breakpoint in the method (after the PostAsync method call). When the PostAsync method returns on a different thread, your debugger should hit the next breakpoint.
My .net application try to access external API by using the code below...
using (var keyClient = new HttpClient())
{
keyClient.BaseAddress = new Uri(ConfigurationManager.AppSettings["webshopurl"]);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("api_username",
ConfigurationManager.AppSettings["webshopAPIUserName"]),
new KeyValuePair<string, string>("api_password",
ConfigurationManager.AppSettings["webshopAPIPassword"])
});
var result = keyClient.PostAsync("/api/v1/key.php", content).Result;
token = result.Content.ReadAsStringAsync().Result;
}
When calling from local machine it works properly. But when it is hosted in online server URL such like http://app.test.net:5000/test it is not calling to the API. If we host such a URL like http://app.test.net/test it is working properly.
What is the reason for this?
Why are you using .Result to unpack the result? It's a lot better to use await to get the result from an async method.
.Result can cause a deadlock if you are not being careful with the context.
Stephen Cleary has a really nice articles that goes into more details.
Don't Block on Async Code
I am working with OAuth at the moment. The problem with the current code is it doesn't wait until the user allows the application on the site and gets the proper key and secret. I was using a threading type wait but, sometimes it not long enough...some users are slower then others. I have attached a snippet of my code. What I would like to know is where to insert a while statement, or should I even use that ?
public OAuthToken GetRequestToken(Uri baseUri, string consumerKey, string consumerSecret)
{
var uri = new Uri(baseUri, "oauth/request_token");
uri = SignRequest(uri, consumerKey, consumerSecret);
var request = (HttpWebRequest) WebRequest.Create(uri);
request.Method = WebRequestMethods.Http.Get;
var response = request.GetResponse();
var queryString = new StreamReader(response.GetResponseStream()).ReadToEnd();
var parts = queryString.Split('&');
var token = parts[1].Substring(parts[1].IndexOf('=') + 1);
var secret = parts[0].Substring(parts[0].IndexOf('=') + 1);
return new OAuthToken(token, secret);
}
You should switch over to the newer System.Net.Http and System.Net.Http.WebRequest libraries that come with .NET now. These all use the new async programming stuff that is available with .NET 4.5.
You can call a request (returning you a task object that you can wait on) and automatically pause the thread for the response. The UI won't respond, as normal. That is probably the easiest thing to do if you don't understand how the new async and await keywords work. For more information on them, see http://msdn.microsoft.com/en-us/library/hh191443.aspx
Here is your code doing things with the new libraries:
using System.Net.Http;
public OAuthToken GetRequestToken(Uri baseUri, string consumerKey, string consumerSecret)
{
var uri = new Uri(baseUri, "oauth/request_token");
uri = SignRequest(uri, consumerKey, consumerSecret);
var message = new HttpRequestMessage(new HttpMethod("GET"), uri);
var handler = new WebRequestHandler();
var client = new HttpClient(handler);
// Use the http client to send the request to the server.
Task<HttpResponseMessage> responseTask = client.SendAsync(message);
// The responseTask object is like a wrapper for the other task thread.
// We can tell this task object that we want to pause our current thread
// and wait for the client.SendAsync call to finish.
responseTask.Wait();
// - Once that thread finishes, and the code continues on, we need to
// tell it to read out the response data from the backing objects.
// - The responseTask.Result property represents the object the async task
// was wrapping, we want to pull it out, then use it and get the content
// (body of the response) back.
// - Getting the response actually creates another async task (the
// .ReadAsStringAsync() call) but by accessing the .Result
// property, it is as if we called .ReadAsStringAsync().Wait(); Except that
// by using Result directly, we not only call Wait() but we get the resulting,
// wrapped object back. Hope that didn't confuse you much :)
var queryString = responseTask.Result.Content.ReadAsStringAsync().Result;
// And all your other normal code continues.
var parts = queryString.Split('&');
var token = parts[1].Substring(parts[1].IndexOf('=') + 1);
var secret = parts[0].Substring(parts[0].IndexOf('=') + 1);
return new OAuthToken(token, secret);
}
Why Not use a modal pop up and then call the authentication class on the submit button