Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does an async method not return the awaitable immediately?

Tags:

c#

async-await

I had thought this was a reasonable pattern to use to call WebClient DownloadData asynchronously in an event handler:

private async void button1_Click(object sender, EventArgs e)
{
    WebClient wc = new WebClient();
    //wc.Proxy = null;
    byte[] bytes = await wc.DownloadDataTaskAsync("http://www.google.com");
    label1.Text = Encoding.ASCII.GetString(bytes);
}

But I find DownloadDataTaskAsync blocks for about 5 seconds before returning (unless the wc.Proxy = null statement is uncommented). What's the point of a method being awaitable if it can at a whim perform non-trivial work before even returning the task?

Presumably this means to be safe I should never call xAsync methods as above but instead should always wrap them in a Task.Run() myself to be sure. Or not?

like image 294
Weyland Yutani Avatar asked Feb 12 '23 05:02

Weyland Yutani


2 Answers

This is a known issue with WebClient/HttpWebRequest: the proxies and DNS lookups are always done synchronously. This is a bug, but Microsoft has pretty much decided not to fix it for backwards compatibility reasons.

The first thing I'd recommend is to use HttpClient. If that doesn't work and you need asynchrony, then you can wrap the call in Task.Run.

like image 149
Stephen Cleary Avatar answered Feb 14 '23 17:02

Stephen Cleary


It turns out that WebClient.DownloadDataTaskAsync is calling HttpWebRequest.BeginGetResponse

MSDN points out:

The BeginGetResponse method requires some synchronous setup tasks to complete (DNS resolution, proxy detection, and TCP socket connection, for example) before this method becomes asynchronous. As a result, this method should never be called on a user interface (UI) thread because it might take considerable time (up to several minutes depending on network settings) to complete the initial synchronous setup tasks before an exception for an error is thrown or the method succeeds.

http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse(v=vs.110).aspx

Unfortunately the MSDN documentation for WebClient.DownloadDataTaskAsync says:

This operation will not block.

which seems to not be strictly true.

like image 42
Weyland Yutani Avatar answered Feb 14 '23 17:02

Weyland Yutani