Gerard
Gerard

Reputation: 13397

Is using async/await better then using task.Start() and why?

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

Answers (3)

Lukazoid
Lukazoid

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

Stephen Cleary
Stephen Cleary

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 Tasks: 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

Noctis
Noctis

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

Related Questions