Reputation: 320
I am trying to measure improvement in amount of time if I use Http Async instead of Sync one, but the code below deadlocks because of Async method contexts I searched and found one can use ConfigureAwait(false) to fix the situation but the code still deadlocks. Any suggestions on how I can fix this?
class Program
{
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
var entities = new List<string>() { "iron+man+3", "dark+knight+rises", "frozen+movie" };
stopwatch.Start();
int taskStatus = AsyncGet(entities).Result;
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedTicks);
stopwatch.Reset();
stopwatch.Start();
SyncGet(entities);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedTicks);
var depTime = DateTime.UtcNow;
depTime = depTime.AddMilliseconds(-depTime.Millisecond);
Console.WriteLine(depTime.ToString("yyyy-MM-ddTHH:mm:ss.fff"));
Console.Read();
}
private static async Task<int> AsyncGet(List<string> entities)
{
var taskHttpList = new List<Task<WebResponse>>();
var taskStreamList = new List<Task<string>>();
var uriTemplate = "https://www.google.co.in/?#q={0}";
foreach (var entity in entities)
{
Uri uri = new Uri(string.Format(uriTemplate, entity));
var request = WebRequest.Create(uri);
taskHttpList.Add(request.GetResponseAsync());
}
foreach (var task1 in taskHttpList)
{
var response = (HttpWebResponse)await task1.ConfigureAwait(false);
taskStreamList.Add((new StreamReader(response.GetResponseStream())).ReadToEndAsync());
}
foreach (var task in taskStreamList)
{
var responseStr = (String)await task.ConfigureAwait(false);
}
return 0;
}
private static void SyncGet(List<string> entities)
{
var uriTemplate = "https://www.google.co.in/?#q={0}";
foreach (var entity in entities)
{
Uri uri = new Uri(string.Format(uriTemplate, entity));
var request = WebRequest.Create(uri);
var response = request.GetResponse();
var str = new StreamReader(response.GetResponseStream()).ReadToEnd();
}
}
}
Upvotes: 2
Views: 961
Reputation: 6882
I imagine that there is a limit on the number of threads handling IO completion events. Instead of processing it in the lockstep fashion build a complete chain of tasks per work item:
private static async Task<int> AsyncGet(List<string> entities)
{
var tasks = new List<Task<string>>();
foreach (var entity in entities)
{
var t = AsyncGetResponse(entity);
tasks.Add(t);
}
await Task.WaitAll(tasks.ToArray()).ConfigureAwait(false);
return 0
}
static async Task<string> AsyncGetResponse(string entity)
{
const string uriTemplate = "https://www.google.co.in/?#q={0}";
Uri uri = new Uri(string.Format(uriTemplate, entity));
var request = WebRequest.Create(uri);
string result;
using (var response = (HttpWebResponse)await request.GetResponseAsync().ConfigureAwait(false))
{
var reader = new StreamReader(response.GetResponseStream()))
result = await (string) reader.ReadToEndAsync().ConfigureAwait(false);
}
return result;
}
As was mentioned in comments, don't forget to dispose allocated resources, such as WebResponse.
Upvotes: 2