【发布时间】:2011-07-05 05:01:00
【问题描述】:
我正在阅读 Eric Lippert 博客上关于 C#5 新异步特性的精彩 article series。在那里,他使用了一个从远程位置获取文档的方法示例,一旦检索到,就将它们存档在存储驱动器上。这是他使用的代码:
async Task<long> ArchiveDocumentsAsync(List<Url> urls)
{
long count = 0;
Task archive = null;
for(int i = 0; i < urls.Count; ++i)
{
var document = await FetchAsync(urls[i]);
count += document.Length;
if (archive != null)
await archive;
archive = ArchiveAsync(document);
}
return count;
}
现在想象一下获取文档的速度非常快。所以第一个文档被获取。之后,它开始被归档,同时正在获取第二个文档。现在想象第二个文档已被提取,而第一个文档仍在存档中。这段代码是开始获取第三个文档还是等到第一个文档被归档?
正如 Eric 在其文章中所说,此代码由编译器转换为:
Task<long> ArchiveDocuments(List<Url> urls)
{
var taskBuilder = AsyncMethodBuilder<long>.Create();
State state = State.Start;
TaskAwaiter<Document> fetchAwaiter = null;
TaskAwaiter archiveAwaiter = null;
int i;
long count = 0;
Task archive = null;
Document document;
Action archiveDocuments = () =>
{
switch(state)
{
case State.Start: goto Start;
case State.AfterFetch: goto AfterFetch;
case State.AfterArchive: goto AfterArchive;
}
Start:
for(i = 0; i < urls.Count; ++i)
{
fetchAwaiter = FetchAsync(urls[i]).GetAwaiter();
state = State.AfterFetch;
if (fetchAwaiter.BeginAwait(archiveDocuments))
return;
AfterFetch:
document = fetchAwaiter.EndAwait();
count += document.Length;
if (archive != null)
{
archiveAwaiter = archive.GetAwaiter();
state = State.AfterArchive;
//----> interesting part! <-----
if (archiveAwaiter.BeginAwait(archiveDocuments))
return; //Returns if archive is still working => Fetching of next document not done
AfterArchive:
archiveAwaiter.EndAwait();
}
archive = ArchiveAsync(document);
}
taskBuilder.SetResult(count);
return;
};
archiveDocuments();
return taskBuilder.Task;
}
补充问题:
如果停止执行,是否可以继续获取文档?如果是,怎么做?
【问题讨论】:
标签: c# asynchronous c#-5.0