简体   繁体   English

使用async / await比使用task.Start()更好吗?为什么?

[英]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"); 用法: 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? 为什么我们更喜欢异步 - 等待其他它是一个很好的模式?

The two methods you post are completely different. 您发布的两种方法完全不同。

DownloadAsync is a truly asynchronous method. DownloadAsync是一种真正的异步方法。 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 . 同步Download通过调用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. 我在我的博客上解释为什么Result不应该与异步Task一起使用 :在一般情况下,它可能导致死锁。 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). 然后,您从TPL任务中调用它,因此它会阻止任务线程(很可能是线程池线程)。 While the data is downloading, that task thread is blocked on that asynchronous operation. 在下载数据时,该异步操作会阻止该任务线程。

So, DownloadAsync is more efficient. 因此, DownloadAsync更有效。

new Task will execute the entire method using TaskScheduler.Current , usually this makes use of the ThreadPool . new Task将使用TaskScheduler.Current执行整个方法,通常这会使用ThreadPool

By using async/await, the method is entered synchronously, and will only use an asynchronous continuation if it is required. 通过使用async / await,该方法是同步进入的,并且只在需要时才使用异步延续。

What I mean by this can be demonstrated with the following LINQPad program: 我的意思可以通过以下LINQPad程序来演示:

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. 尝试将delay更改为0,您将看到继续在同一线程上恢复,这是因为如果没有延迟, Task.Delay立即返回,这避免了在不需要时安排和执行延续的开销。

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. 通过使用new Task ,您将失去这个聪明的功能并始终使用ThreadPool线程,即使异步方法的实现者可能认为不必要。

Have a look at this post , Stephen Cleary explains exactly the why and the differences. 看看这篇文章 ,Stephen Cleary确切地解释了原因和差异。

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(). 我发现async / await在眼睛上也更好,因为你将在另一个方法中拥有额外的代码,而不需要放置task.Start()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM