async httpclient operation - c#

I am trying to design a browser that will fetch site updates programmatically. I am trying to do this with async/await methods but when I try and run the program it seems to just hang on response.Wait();. not sure why or whats happening.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var urls = sourceUrls();
Task<HttpResponseMessage> response = login(urls[0]);
response.Wait();
Console.Write( "Complete" );
}
private List<Site> sourceUrls()
{
var urls = new List<Site>();
urls.Add(new Site("http://yahoo.com", "test", "test"));
return urls;
}
}
browser class::
static public class Browser
{
private static CookieContainer cc = new CookieContainer();
private static HttpClientHandler handler = new HttpClientHandler();
public static HttpClient browser = new HttpClient(handler);
static Browser()
{
handler.CookieContainer = cc;
}
static public async Task<HttpResponseMessage> login(Site site)
{
var _postData = new Dictionary<string, string>
{
{"test", "test"}
};
FormUrlEncodedContent postData = new FormUrlEncodedContent(_postData);
HttpResponseMessage response = await browser.PostAsync(site.url, postData);
return response;
}
}
Also, for my intended purposes, is it ok to make browser a static function, or does that not make sense? Sorry for the questions, new to c#

It's a bad idea to call Wait on a Task in a UI thread, it results in a deadlock.
You can simply await the response which will achieve what you want. The await unwraps the response from the Task so your return type is now just HttpResponseMessage. Because you can't mark constructors as async you can move the functionality to another method that kicks off the operation.
public MainWindow()
{
InitializeComponent();
LoadUrlsAsync();
}
public async Task LoadUrlsAsync()
{
var urls = sourceUrls();
HttpResponseMessage response = await login(urls[0]);
Console.Write( "Complete" );
}
See this article for best practices when using async/await.
Alternatively you can use the Task.ConfigureAwait extension method to configure the continuation not to run on the current SyncrhronizationContext which should also avoid the deadlock.
public MainWindow()
{
InitializeComponent();
var urls = sourceUrls();
Task<HttpResponseMessage> response = login(urls[0]).ConfigureAwait(false);
response.Wait();
Console.Write( "Complete" );
}

Wait causes a deadlock that I explain in full on my blog. The best solution is to use await as Ned suggested.
In your case, constructors cannot be async, so that's not possible. This should be an indication that what you're trying to do may not be the best thing to do. In particular, you're trying to block the UI thread waiting for a download to complete; this is almost never a good idea.
Instead, have your constructor start the asynchronous operation and (synchronously) load a view that shows no data - e.g., a "loading" screen or an empty view, whatever makes the most sense for your problem domain. Then, when the asynchronous operation completes, it should update the view with the new data. I have an article on async data binding that explores one possible technique.

Both GetUrl() and GetUrl2(), below, accomplish what you're looking to do in slightly different ways. Be aware, however, that Task.Wait will block the current thread (in this case, the UI thread) until the task completes. I'm guessing this isn't what you want to do.
using System.Diagnostics;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
GetUrls();
GetUrls2();
}
private void GetUrls()
{
var response = Task.Run(() => Browser.login("http://yahoo.com"));
response.Wait();
Debug.WriteLine("Complete GetUrls()");
}
private void GetUrls2()
{
var browseTask = Browser.login("http://yahoo.com");
browseTask.ContinueWith((r) => Debug.WriteLine("Complete GetUrls2()"));
}
}
static public class Browser
{
static public async Task<HttpResponseMessage> login(string site)
{
var browser = new HttpClient();
return await browser.GetAsync(site);
}
}

Related

C# stops working when performing async post request

I am working on a mobile app, and the problem is that when I perform a async request ( PostAsync ) using Net.Http my program stops running.
Here is my request class, where I perform the requests using Net.Http.
...
namespace BSoft.Requests
{
public class Requests
{
public Requests(){}
public static string HostName = "https://dev5.360businesssoft.com/";
private static readonly HttpClient httpClient = new HttpClient();
public static async Task<string> PerformPostRequest(Dictionary<string, string> values, string path)
{
string url = HostName + path;
FormUrlEncodedContent content = new FormUrlEncodedContent(values);
HttpResponseMessage response = await httpClient.PostAsync(url, content);
string responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
}
}
and here is my login class, where I call call the request and display the result as string.
...
namespace BSoft.Login
{
public class Login
{
public Login()
{
}
public static void PerformLogin(string username, string password, bool remember)
{
var values = new Dictionary<string, string>();
values.Add("User", username);
values.Add("Password", password);
var ReturnedObj = Requests.Requests.PerformPostRequest(values, "test.php").Result;
System.Diagnostics.Debug.WriteLine(ReturnedObj);
}
}
}
This is a screenshot of the app, you can notice that the button is freezed
The call to Result is blocking the gui thread. Instead, await the result:
var ReturnedObj = await Requests.Requests.PerformPostRequest(values, "test.php");
System.Diagnostics.Debug.WriteLine(ReturnedObj);
Your call to Result will block the gui thread until PerformPostRequest completes, so there's not really a lot of point using the async features here. If you really don't want the code to execute asynchronously then you might as well remove the calls to the async methods and make the calls synchronous.
Try
string returnedString = await Requests.Requests.PerformPostRequest(values, "test.php");

Async for Long operation with HttpResponseMessage

I am figuring out performance of my C# web api. I wrote a very simple HelloWorld response:
public class HelloWorldController : ApiController
{
public HttpResponseMessage Get()
{
return new HttpResponseMessage()
{
Content = new StringContent("HelloWorld")
};
}
}
I tested by using JMeter I set 1000 Users request and it worked perfectly (CPU usage up to 100%). But the problem is that when the operation of the api take bit longer, the response become worse, got only 3 responses each (CPU usage <7%). It took minuets for 1000 users request.
public HttpResponseMessage Get()
{
Thread.Sleep(1000);
return new HttpResponseMessage()
{
Content = new StringContent("HelloWorld")
};
}
After google I come up with idea of using async but still I got same problem. I don't know what the problem is or my code implementation. Below is my sample implementation.
public async Task<HttpResponseMessage> Get()
{
return new HttpResponseMessage()
{
Content = new StringContent(await LongOperationAsync())
};
}
private string LongOperation()
{
//long operation here
Thread.Sleep(1000);
return "HelloWorld";
}
private Task<string> LongOperationAsync()
{
return Task.Factory.StartNew(() => LongOperation());
}
Anyone know what is the problem or any idea regarding to this problem?
async and await are not magic bullets that just "mak teh codez moah awesomz". On ASP.NET, await enables your application to be more scalable (and respond to changes in scale more quickly) by making optimum use of the thread pool.
So, if you're freeing up a thread pool thread (await) but using up another thread pool thread (StartNew), you're not going to gain anything. In particular, exposing a fake-async method for a synchronous API is an antipattern.
If possible, the best solution is to make LongOperationAsync a naturally-asynchronous operation:
public async Task<HttpResponseMessage> Get()
{
return new HttpResponseMessage()
{
Content = new StringContent(await LongOperationAsync())
};
}
private async Task<string> LongOperationAsync()
{
//long operation here
await Task.Delay(1000);
return "HelloWorld";
}
If this isn't possible, then you may as well keep it synchronous. Using Task.Run (or even worse, StartNew) isn't going to help at all.
The Method LongOperationAsync And LongOperation also should be async :
private async Task<string> LongOperation()
{
//long operation here
await Task.Delay(1000);
return "HelloWorld";
}
private async Task<string> LongOperationAsync()
{
var rt = await Task.Run(() => LongOperation());
return rt;
}
see:
Asynchronous programming

Async is becoming a pain in the behind because I'm trying to make a re-usable library that doesn't suck

Because Post requests to APIs need to run asynchronously on windows phone, I am struggling to create a lean easy to use library to interact with an API.
The issue is that people using the library will always need to supply a callback function.
Let's take a look at some pseudo code:
PostRequest Class to help me with POST requests:
class PostRequest
{
private Action<MemoryStream> Callback;
public PostRequest(string urlPath, string data, Action<MemoryStream> callback)
{
Callback = callback;
// Form the URI
UriBuilder fullUri = new UriBuilder(urlPath);
if (!string.IsNullOrEmpty(data))
fullUri.Query = data;
// Initialize a new WebRequest
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(fullUri.Uri);
request.Method = "POST";
// Set up the state object for the async request
DataUpdateState dataState = new DataUpdateState();
dataState.AsyncRequest = request;
// Start the asynchronous request
request.BeginGetResponse(new AsyncCallback(HandleResponse),
dataState);
}
private void HandleResponse(IAsyncResult asyncResult)
{
// Get the state information
DataUpdateState dataState = (DataUpdateState)asyncResult.AsyncState;
HttpWebRequest dataRequest = (HttpWebRequest)dataState.AsyncRequest;
// End the async request
dataState.AsyncResponse = (HttpWebResponse)dataRequest.EndGetResponse(asyncResult);
if (dataState.AsyncResponse.StatusCode.ToString() == "OK")
{
// Create a stream from the response
Stream response = dataState.AsyncResponse.GetResponseStream();
TextReader textReader = new StreamReader(response, true);
string jsonString = textReader.ReadToEnd();
MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
// Send the stream through to the callback function
Callback(stream);
}
}
}
public class DataUpdateState
{
public HttpWebRequest AsyncRequest { get; set; }
public HttpWebResponse AsyncResponse { get; set; }
}
The API Access Object classes:
class APIAuthenticationCredentials
{
public String Username { get; set; }
public String Password { get; set; }
}
class APIAO
{
private String AuthUrl = "http://api.example.com/";
public static Auth Auth = new Auth();
//...
public static void Authenticate( String data, APIAuthenticationCredentials credentials, Action<MemoryStream> callback )
{
PostRequest request = new PostRequest(AuthURL, data, callback);
}
//...
}
You will notice I have to pass a callback function all the way through this so that once the data is returned by the HandleResponse method in my PostRequest class, the data is forwarded onto some controller that makes the screen do something with the data. At the moment, it's not ultra horrid to use:
private void DisplayData(MemoryStream stream)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Auth));
APIAO.Auth = (Auth)serializer.ReadObject(stream);
}
//...
APIAuthenticationCredentials credentials = new APIAuthenticationCredentials {
Username = "whatever",
Password = "whatever"
}
APIAO.Authenticate( credentials, DisplayData );
//...
The problem is I want to create some kind of repository style pattern... Let's say the API returned different json models, one call returned an array of products... the problem is that I want to create one lovely repository call eg:
IProductRepository productRepository = new ProductRepository();
productRepository.GetAll();
But I've gotta put some GOSH DARN callback function in it too and that means every repository method of any object type returned by the API is going to have this MemoryStream callback... and if I ever want to change that functionality, I've gotta update that stuff everywhere yo. :(
Has anyone seen a better way of doing this crap.
This is starting to become far too complex
--crying
A simpler answer using newer language constructs would be:
public static Task<string> GetData(string url, string data)
{
UriBuilder fullUri = new UriBuilder(url);
if (!string.IsNullOrEmpty(data))
fullUri.Query = data;
WebClient client = new WebClient();
client.Credentials = CredentialCache.DefaultCredentials;//TODO update as needed
return client.DownloadStringTaskAsync(fullUri.Uri);
}
In a 4.0 project you can use a TaskCompletionSource to translate a non-Task asynchronous model into a Task:
public static Task<string> GetData2(string url, string data)
{
UriBuilder fullUri = new UriBuilder(url);
if (!string.IsNullOrEmpty(data))
fullUri.Query = data;
WebClient client = new WebClient();
client.Credentials = CredentialCache.DefaultCredentials;//TODO update as needed
var tcs = new TaskCompletionSource<string>();
client.DownloadStringCompleted += (s, args) =>
{
if (args.Error != null)
tcs.TrySetException(args.Error);
else if (args.Cancelled)
tcs.TrySetCanceled();
else
tcs.TrySetResult(args.Result);
};
client.DownloadStringAsync(fullUri.Uri);
return tcs.Task;
}
The caller now has a Task<string> that represents the results of this asynchronous operation. They can wait on it synchronously and get the result using the Result property, they can add a callback that will execute when the operation finishes using ContinueWith, or they can await the task in an async method which, under the hood, will wire up the remainder of that method as a continuation of that task, but without creating a new method or even a new scope, i.e.
public static async Task Foo()
{
string result = await GetData("http://google.com", "");
Console.WriteLine(result);
}
This will start the asynchronous task, add a callback (or continuation) to that task so that when it runs it will continue executing code where it left off, at which point it will then write the results to the console and mark the Task that this method returns as completed, so that any continuations to this method will then execute (allowing for composition of async methods).

HttpClient await hangs on PostAsync with async void method

I'm still trying to wrap my head around async and I'm wondering why the following code is causing a deadlock. My use case is this: I have a service interface which attempts to abstract how the service is implemented. One of the services is an OAuth based web-service. The service interface has a method Connect() which anyone using the interface must do prior to using it.
On my client side I create my concrete service object and call Connect() in my view constructor (this is a prototype, so I'm just trying to get a proof of concept going). In the OAuth-based service, the connect call requires retrieving an access token, so it (attempts) to do this asynchronously. This Connect() call never returns, though, and the application is deadlocked (but the UI is active). I'm guessing I'm messing up and trying to synchronously use my client somewhere, but I'm not sure where.
Control
public class MainWindow
{
public MainWindow()
{
InitializeComponent();
_webService = new OAuthBasedWebService();
_webService.ShowAuthorizationPage += _webService_ShowAuthorizationPage; // this is defined on the concrete object -- i know, bad design
_webService.Connect();
}
}
OAuth based webservice
public class OAuthBasedWebService()
{
private OAuthWrapper _wrapper;
public async void Connect()
{
var uri = await _wrapper.GetAuthorizationUri();
OnShowAuthorizationPage(uri);
}
}
internal class OAuthWrapper
{
public async Task<Uri> GetAuthorizationUri()
{
var uri = await _consumer.GetAuthorizationUriAsync();
return uri;
}
}
internal class OAuthConsumer
{
public async Task<Uri> GetAuthorizationUriAsync()
{
using (var client = new HttpClient())
{
client.BaseAddress = "webservicebaseaddress";
var content = new FormUrlEncodedContent(new []
{
CreateParameter("oauth_consumer_key", "consumerkey"),
CreateParameter("oauth_consumer_secret", "consumersecret")
// etc., etc.
});
var response = await client.PostAsync("/method_path", content).ConfigureAwait(false);
var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
// parse authorization uri from responseContent
return authorizationUri;
}
}
}
I know the design needs a little work but I'm trying to figure out why this is deadlocking. I'm guessing it is because _webService.Connect() is not being called asynchronously but I also cannot await that because it doesn't return anything and the rest of the program doesn't depend on it.
I'm not sure why you are using a event here, if the problem was just because you couldn't make the constructor "async" then just move the conect call to another method:
public class MainWindow
{
public MainWindow()
{
InitializeComponent();
Init();
}
public async void Init(){
_webService = new OAuthBasedWebService();
Uri uri=await _webService.Connect();
_webService_ShowAuthorizationPage(uri);
}
}
public class OAuthBasedWebService()
{
private OAuthWrapper _wrapper;
public async Task<Uri> Connect()
{
return await _wrapper.GetAuthorizationUri();
}
}

Async task does not end

I'm trying to start async task (on .NET 4.5) which downloads content of web page, but somehow this task never finishes.
My PageDownloader class:
using System.Net;
using System.Text;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using System;
namespace ParserConsole.WebClient
{
public class PageDownloader
{
private System.Net.Http.HttpClient _client;
public PageDownloader()
: this(Encoding.UTF8) { }
private Encoding _encoding;
public PageDownloader(Encoding encoding)
{
_encoding = encoding;
_client = new HttpClient() { Timeout = TimeSpan.FromSeconds(10)};
}
private HttpRequestMessage _request;
private HttpResponseMessage _response;
private string _responseString;
public string GetPageData(string link)
{
_request = new HttpRequestMessage(HttpMethod.Get, link);
_request.Headers.Add("User-Agent", "Chrome/21.0.1180.89");
_request.Headers.Add("Accept", "text/html");
GetResponse().Wait();
GetStringFromResponse().Wait();
return _responseString;
}
private async Task<HttpResponseMessage> GetResponse() {
return _response = await _client.GetAsync(_request.RequestUri);
}
private async Task<string> GetStringFromResponse() {
return _responseString = await _response.Content.ReadAsStringAsync();
}
}
}
I start downloading page by calling
new PageDownloader().GetPageData(url);
When I'm trying to debug the code, everything is fine till GetResponse().Wait(). But somehow GetResponse() task never finishes - breakpoint on the next line is never reached. I get no exceptions, application continues running. Any suggestions?
This is a standard deadlock condition you get when you start an async operation and then block on the returned task.
Here is a blog post discussion the topic.
Basically, the await call ensures that the continuation it wires up of the task will run in the context you were originally in (which is very helpful) but because you are calling Wait in that same context it's blocking, so the continuation never runs, and that continuation needs to run for the wait to end. Classic deadlock.
As for the fix; usually it means you just shouldn't be doing a blocking wait on the async operation; it's contrary to the design of the whole system. You should, "async all the way up". In this case it would mean that GetPageData should return a Task<string> rather than a string, and rather than waiting on the other operations that return a task you should await on them.
Now, having said that, there are ways of doing a blocking wait on the async operations without deadlocking. While it can be done, it honestly defeats the purpose of using async/await in the first place. The primary advantage of using that system is that the main context isn't blocked; when you block on it that entire advantage goes away, and you might as well just use blocking code all the way through. async/await is really more of an all-or-nothing paradigm.
Here is how I would structure that class:
public class PageDownloader
{
private System.Net.Http.HttpClient _client;
private Encoding _encoding;
public PageDownloader()
: this(Encoding.UTF8) { }
public PageDownloader(Encoding encoding)
{
_encoding = encoding;
_client = new HttpClient() { Timeout = TimeSpan.FromSeconds(10) };
}
public async Task<string> GetPageData(string link)
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, link);
request.Headers.Add("User-Agent", "Chrome/21.0.1180.89");
request.Headers.Add("Accept", "text/html");
HttpResponseMessage response = await _client.GetAsync(request.RequestUri);
return await response.Content.ReadAsStringAsync(); ;
}
}
Why not just do this if you want to have a function like that.
public string GetPageData(string link)
{
_request = new HttpRequestMessage(HttpMethod.Get, link);
_request.Headers.Add("User-Agent", "Chrome/21.0.1180.89");
_request.Headers.Add("Accept", "text/html");
var readTask = _client.GetStringAsync(link);
readTask.Wait();
return readTask.Result;
}
It would be better to return the Task all the way back and handle it with async/await in the calling code.
public Task<string> GetPageData(string link)
{
_request = new HttpRequestMessage(HttpMethod.Get, link);
_request.Headers.Add("User-Agent", "Chrome/21.0.1180.89");
_request.Headers.Add("Accept", "text/html");
return _client.GetStringAsync(link);
}

Categories

Resources