I like the new System.Net.Http.HttpClient class. It has a nice simple API, it doesn't throw on normal errors. But its async only.
I need code that goes (deep inside a server)
foo();
bar();
// compute stuff
var x = GetThingFromOtherServerViaHttp();
// compute more stuff
wiz(x);
classic sequential synchronous code. I saw several SO question that were similar but never actually ended up saying 'do this'. I looked at
client.PostAsync.Wait()
the world screams 'dont do this'. How about:
client.PostAsync.Result()
isnt this just Wait in disguise?
In the end I ended up passing in a lambda callback that processed the result and then awoke the calling thread that was explicitly waiting on a EventWaitHandle. A lot of plumbing. Is there something a little simpler or shoul I just go back to using the old http clients
EDIT:After further reading I suspect that this code has the same issues as Wait and Result, its just a more longwinded deadlock
EDIT: I had MS PM confirm to me recently that there is a mandate 'any API that might take > X ms (I forgot X) must be async', many PMs interpret this as 'async only' (not clear if this is what is intended). Hence the Document DB api being only async.
Try the following: var task = Task. Run(() => myHttpClient. GetAsync(someUrl)); task.
HttpClient.SendAsync Method (System.Net.Http)Send an HTTP request as an asynchronous operation.
In a nutshell, WebRequest—in its HTTP-specific implementation, HttpWebRequest—represents the original way to consume HTTP requests in . NET Framework. WebClient provides a simple but limited wrapper around HttpWebRequest. And HttpClient is the new and improved way of doing HTTP requests and posts, having arrived with .
HttpClient is a very important class in the . NET/. NET Core ecosystem. HttpClient is designed as a shared instance that is also a thread-safe if used properly.
From http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx:
return Task.Run(() => Client.PostAsync()).Result;
@Noseratio - of course I am concerned about deadlocks :-)
You only would be concerned about deadlocks if you're on a thread with synchronization context.
That would normally be either the main thread of a UI application (client-side), or random ASP.NET thread processing an HTTP request (server-side). In either case you really shouldn't be blocking it.
The accepted answer might help mitigating the deadlock, but blocking like this would still hurt the end user experience of your UI app (the UI would be frozen), or the server-side app scalability (a thread wasted with blocking, while it could be serving another request). Just don't block and use async/await
all the way through.
You mentioned "deep inside a server" but provided no details on what kind of server-side app is that. Most of the modern server-side frameworks have a good plumbing for async/await
, so it shouldn't be a problem embracing it.
Updated to address the comment:
I still dont like the fact that the same code written in different places will deadlock. I would expect the wait call in a deadlock-prone environment to throw
This is not particularly a problem of async/await
but is that of synchronization context concept in general, when it's used with blocking code. Here is the deadlock in a nutshell:
private void Form1_Load(object sender, EventArgs e)
{
var mre = new System.Threading.ManualResetEvent(initialState: false);
System.Threading.SynchronizationContext.Current.Post(_ =>
mre.Set(), null);
mre.WaitOne();
MessageBox.Show("We never get here");
}
In theory, it might be possible to try to mitigate potential deadlocks inside SynchronizationContext.Post
, say by checking Thread.ThreadState == System.Threading.ThreadState.WaitSleepJoin
. That would not however be a 100% reliable solution.
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