比较以下两种方法:
static async Task<int> DownloadAsync(string url)
{
var client = new WebClient();
var awaitable = client.DownloadDataTaskAsync(url);
byte[] data = await awaitable;
return data.Length;
}用法: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);
}用法:
Task task = new Task(() => Download("http://stackoverflow.com"));
task.Start();据我所见,这两种方法都异步运行。我的问题是:
这两种方法在行为上有什么区别吗?
为什么我们更喜欢异步等待他人,那么它是一个很好的模式?
发布于 2013-11-17 00:58:57
new Task将使用TaskScheduler.Current执行整个方法,通常使用ThreadPool。
通过使用异步/等待,方法是同步输入的,并且只有在需要时才会使用异步延续。
下面的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();
}尝试将delay更改为0,您将看到继续在同一个线程上继续,这是因为Task.Delay只是在没有延迟的情况下立即返回,这避免了在不需要的情况下安排和执行连续性的开销。
通过使用new Task,您将失去这一巧妙的功能,并且总是使用ThreadPool线程,即使异步方法的实现者可能不认为它是必要的。
发布于 2013-11-17 02:44:52
您发布的两种方法完全不同。
DownloadAsync是一种真正的异步方法。这意味着,当数据正在下载时,在该异步操作上没有阻塞的线程。
Download通过调用Task.Result来同步阻塞调用线程。我在我的博客S上解释:在一般情况下,它会导致死锁。但让我们假设没有死锁。然后从TPL任务调用它,因此它阻塞任务线程(很可能是线程池线程)。当数据正在下载时,该任务线程将在该异步操作上被阻塞。
因此,DownloadAsync更有效。
发布于 2013-11-17 00:58:17
看看这个帖子,Stephen准确地解释了原因和差异。
总之,这是完全一样的。这是新的和旧的等待方式。我发现异步/等待也更友好,因为其他方法中有额外的代码,并且不需要放置task.Start()。
https://stackoverflow.com/questions/20025858
复制相似问题