enrique7mc
enrique7mc

Reputation: 907

Difference between HttpClient.GetStringAsync and WebClient.DownloadStringAsync

I have the following code

static void Main(string[] args)
{
        string url = "http://www.google.com";
        Console.WriteLine(GetUrl(url).Result); // throws TaskCanceledException
        Console.WriteLine(GetUrl2(url).Result);
    }

    public static Task<string> GetUrl(string url)
    {
        using (var client = new HttpClient())
        {
            return client.GetStringAsync(url);
        }
    }

    public static Task<string> GetUrl2(string url)
    {
        using (var client = new WebClient())
        {
            return client.DownloadStringTaskAsync(url);
        }
    }

I'm trying to get the string of an url, the problem is GetUrl method (uses HttpClient's GetStringAsync) throws an TaskCacelledException, but GetUrl2 method (uses WebClient's DownloadStringTaskAsync) runs correctly. Is this caused due to using statement? What am I missing?

Edit. In this example I'm calling Result on the task because this is a console application, I know that it is best to await the result in a event handler for example.

Upvotes: 6

Views: 6677

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 456352

Is this caused due to using statement?

Yes. In both code examples, you're disposing the underlying client before the operation completes. Both code examples should be changed as such:

public static async Task<string> GetUrlAsync(string url)
{
    using (var client = new HttpClient())
    {
        return await client.GetStringAsync(url);
    }
}

public static async Task<string> GetUrl2Async(string url)
{
    using (var client = new WebClient())
    {
        return await client.DownloadStringTaskAsync(url);
    }
}

The behavior of asynchronous downloads when their underlying clients are disposed is undocumented. It's best not to dispose the clients until your code is done using them.

Upvotes: 9

Related Questions