我看不出 C#(和 VB)的新异步功能和 .NET 4.0 的Task Parallel Library之间有什么不同。以 Eric Lippert的代码为例:
async void ArchiveDocuments(List<Url> urls) {
Task archive = null;
for(int i = 0; i < urls.Count; ++i) {
var document = await FetchAsync(urls[i]);
if (archive != null)
await archive;
archive = ArchiveAsync(document);
}
}
该await
关键字似乎有两个不同的目的。第一次出现 ( FetchAsync
) 似乎意味着“如果稍后在方法中使用此值并且其任务未完成,请等到它完成后再继续。” 第二个实例 ( archive
) 似乎意味着“如果此任务尚未完成,请立即等待它完成。” 如果我错了,请纠正我。
难道就不能这么简单地写成这样吗?
void ArchiveDocuments(List<Url> urls) {
for(int i = 0; i < urls.Count; ++i) {
var document = FetchAsync(urls[i]); // removed await
if (archive != null)
archive.Wait(); // changed to .Wait()
archive = ArchiveAsync(document.Result); // added .Result
}
}
我已将第一个替换await
为Task.Result
实际需要该值的位置,将第二个await
替换Task.Wait()
为实际发生等待的位置。该功能(1)
已经实现,并且(2)
在语义上更接近代码中实际发生的情况。
我确实意识到一个async
方法被重写为状态机,类似于迭代器,但我也看不到它带来了什么好处。任何需要另一个线程来操作的代码(例如下载)仍然需要另一个线程,并且任何不需要的代码(例如从文件中读取)仍然可以利用 TPL 仅与单个线程一起工作。
我显然在这里遗漏了一些巨大的东西。任何人都可以帮助我更好地理解这一点吗?