Reputation: 13397
Compare the following two methods:
static async Task<int> DownloadAsync(string url)
{
var client = new WebClient();
var awaitable = client.DownloadDataTaskAsync(url);
byte[] data = await awaitable;
return data.Length;
}
usage: Task<int> task = DownloadAsync("http://stackoverflow.com");
static Task<int> Download(string url)
{
var client = new WebClient();
var task = client.DownloadDataTaskAsync(url);
byte[] data = task.Result;
return Task.FromResult(data.Length);
}
usage:
Task task = new Task(() => Download("http://stackoverflow.com"));
task.Start();
As far as I can see both methods run asynchronously. My questions are:
Is there any difference in behavior between the two methods?
Why do we prefer async-await other then it being a nice pattern?
Upvotes: 4
Views: 4059
Reputation: 19416
new Task
will execute the entire method using TaskScheduler.Current
, usually this makes use of the ThreadPool
.
By using async/await, the method is entered synchronously, and will only use an asynchronous continuation if it is required.
What I mean by this can be demonstrated with the following LINQPad program:
const int delay = 1;
public async Task DoSomethingAsync()
{
Thread.CurrentThread.ManagedThreadId.Dump();
await Task.Delay(delay).ConfigureAwait(false);
Thread.CurrentThread.ManagedThreadId.Dump();
}
void Main()
{
DoSomethingAsync().Wait();
}
Try changing delay
to 0, and you will see the the continuation resumes on the same thread, this is because Task.Delay
just returns immediately if there is no delay, this avoids the overhead of arranging and executing continuations when they are not required.
By using new Task
, you are losing this clever functionality and always using a ThreadPool
thread, even when the implementor of an async method may not deem it necessary.
Upvotes: 3
Reputation: 456427
The two methods you post are completely different.
DownloadAsync
is a truly asynchronous method. This means that while the data is downloading, there are no threads blocked on that asynchronous operation.
Download
synchronously blocks the calling thread by calling Task.Result
. I explain on my blog why Result
should not be used with asynchronous Task
s: in the general case, it can cause deadlocks. But let's assume there's no deadlock. You then call it from a TPL task, so it blocks the task thread (most likely a thread pool thread). While the data is downloading, that task thread is blocked on that asynchronous operation.
So, DownloadAsync
is more efficient.
Upvotes: 7
Reputation: 11763
Have a look at this post, Stephen Cleary explains exactly the why and the differences.
In short, it's quite the same. It's the new vs. old way of waiting. I find the async / await being nicer on the eyes as well, since you'll have the extra code in the other method, and don't need to put the task.Start().
Upvotes: 0