gpt4 book ai didi

c# - C#5.0中的异步:Eric Lippert的示例如何工作?

转载 作者:太空宇宙 更新时间:2023-11-03 17:34:53 25 4
gpt4 key购买 nike

我正在阅读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;
}


附加问题:

如果执行停止,是否可以继续获取文档?如果是,怎么办?

最佳答案

这一段代码是开始获取第三个文档,还是等到第一个文档被存档后才开始?


等待。本文的重点是描述控制流如何与转换一起工作,而不是实际描述用于管理fetch-archive操作的最佳系统。

假设您确实有一百个文档要提取和存档,并且您实际上并不关心它们的执行顺序。(*)您可以创建一个新的异步方法“ FetchAndArchive”,该方法异步获取一个文档,然后异步存档。然后,您可以从另一个执行一百个任务的异步方法中调用该方法一百次,每个任务以异步方式获取文档并将其存档。该方法的结果是一个组合的任务,代表执行这一百个任务的工作,每个任务代表执行两个任务的工作。

在这种情况下,只要其中一个提取操作无法立即产生结果,就可以运行准备执行其归档步骤的任务之一。

在本文中,我不想讨论任务组合器。我想专注于更简单的控制流程。



(*)如果操作不是“获取本系列的下一个视频并播放”,而不是“下载文档并存档”,则您可能会关心它们的顺序。即使它们可以更有效地乱序播放,您也不希望它们乱序播放。而是要在当前播放的同时下载下一个。

关于c# - C#5.0中的异步:Eric Lippert的示例如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5132873/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com