2

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();
        }
    }
}
6
  • Have you tried implementing AsyncGet similar to SyncGet, i.e. one foreach loop with two "awaits" inside? Commented Aug 8, 2015 at 6:56
  • Yes and that works but then the whole idea of HTTP async is lost. I am just trying to understand if start a bunch of HTTP async request and then await on them after all requests have started do I get any performance improvement in terms of time taken. Commented Aug 8, 2015 at 9:24
  • 2
    You are not disposing of anything. This might cause the connection pool to become exhausted causing blocking. Dispose all resources. Commented Aug 8, 2015 at 10:15
  • 1
    @user1017860: 1) Async isn't faster than sync; that's not what async is about. 2) Applying "solutions" like ConfigureAwait(false) without understanding them will only complicate the code, not correct it. Commented Aug 8, 2015 at 11:12
  • @Stephen As per my understanding Async is useful when you have lot of Network bound or I/O bound request. And I have a lot of WebRequest in this specific scenario. Can you explain why Async does not fit over here. I am new to Async programming so not very clear where it is useful in practical sense. Can you also give an example of a Console Application type of scenario where Async is useful. Commented Aug 9, 2015 at 1:08

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.