I have an AsyncController and a homepage that queries the user's friends list and does some database work with them. I implemented the async action method pattern for any requests that call external web services. Is this an efficient way of handling this situation? During times of high request volume I am seeing IIS being thread-starved at times and I worry that my nested Async magic may somehow be involved in this.
My main questions/talking points are:
Example code:
public void IndexAsync()
{
AsyncManager.OutstandingOperations.Increment();
User.GetFacebookFriends(friends => {
AsyncManager.Parameters["friends"] = friends;
AsyncManager.OutstandingOperations.Decrement();
});
}
public ActionResult IndexCompleted(List<Friend> friends)
{
return Json(friends);
}
User.GetFacebookFriends(Action<List<Friend>>) looks like this:
void GetFacebookFriends(Action<List<Friend>> continueWith) {
var url = new Uri(string.Format("https://graph.facebook.com/etc etc");
HttpWebRequest wc = (HttpWebRequest)HttpWebRequest.Create(url);
wc.Method = "GET";
var request = wc.BeginGetResponse(result => QueryResult(result, continueWith), wc);
// Async requests ignore the HttpWebRequest's Timeout property, so we ask the ThreadPool to register a Wait callback to time out the request if needed
ThreadPool.RegisterWaitForSingleObject(request.AsyncWaitHandle, QueryTimeout, wc, TimeSpan.FromSeconds(5), true);
}
QueryTimeout just aborts the request if it takes longer than 5 seconds.
The fully asynchronous method you first describe is best, as this releases TP threads back to the pool for reuse. It's highly likely that you're performing some other blocking action elsewhere. What happens in QueryResponse? Although you fetch the response asynchronously, are you also reading the response stream asynchronously? If not, make it so, then TP starvation should be reduced.
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