gpt4 book ai didi

c# - 使用 yield 来推迟 Azure blob 存储调用 - c#

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

我目前有一种方法可以从 Azure 中提取 blob 文件名列表。方法如下:

internal async Task<IEnumerable<BlobItem>> GetFiles(CloudBlobContainer container, string directoryName, bool recursive)
{
var results = new List<BlobItem>();
BlobContinuationToken continuationToken = null;

do
{
var response = await container.GetDirectoryReference(directoryName).ListBlobsSegmentedAsync(false, BlobListingDetails.None, 100, continuationToken, null, null);

continuationToken = response.ContinuationToken;
foreach (var item in response.Results)
{
if (item.GetType() != typeof(CloudBlobDirectory))
results.Add(new BlobItem(item));
else if (recursive)
results.AddRange(await GetFiles(container, ((CloudBlobDirectory)item).Prefix, recursive));
}
}
while (continuationToken != null);

return results;
}

我不喜欢上面的代码的是,我运行所有文件并添加到结果中,直到取消标记为空。所以基本上,去获取所有,然后停下来返回。

我不认为这过于高效 - 我想我也许可以产生结果,所以它只会在我准备好时(从调用代码)获取下一个“批处理”结果。

我不太熟悉使用yield并提出了这个,但我认为它可能不会推迟对ListBlobSegment的调用。这是我的代码:

internal IEnumerable<BlobItem> GetFiles(CloudBlobContainer container, string directoryName, bool recursive)
{
var results = new List<BlobItem>();
BlobContinuationToken continuationToken = null;

do
{
var response = container.GetDirectoryReference(directoryName).ListBlobsSegmentedAsync(false, BlobListingDetails.None, 100, continuationToken, null, null).GetAwaiter().GetResult();

continuationToken = response.ContinuationToken;
foreach (var item in response.Results)
{


if (item.GetType() != typeof(CloudBlobDirectory))
yield return new BlobItem(item);
else if (recursive)
{
var internalResponse = GetFiles(container, ((CloudBlobDirectory)item).Prefix, recursive));
foreach (var intItem in internalResponse)
{
yield return intItem;
}
}
}
}
while (continuationToken != null);
}

如果我以正确的方式使用 yield 语句,有人可以建议我吗?如前所述,以前从未在愤怒中使用过此功能,并且希望正确使用它:-) 我的目标是希望推迟服务调用并使代码对于调用更有效。

提前感谢您的指点!

注意:使用这些 API 进行 Blob 存储

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;

最佳答案

编辑于2018-11-15C#8开始,您将能够使用IAsyncEnumerable :

async IAsyncEnumerable<int> GetBigResultsAsync()
{
await foreach (var result in GetResultsAsync())
{
if (result > 20) yield return result;
}
}

IAsyncEnumerable<string> GetAsyncAnswers()
{
return AsyncEnum.Enumerate<string>(async consumer =>
{
foreach (var question in GetQuestions())
{
string theAnswer = await answeringService.GetAnswer(question);
await consumer.YieldAsync(theAnswer);
}
});
}

https://blogs.msdn.microsoft.com/dotnet/2018/11/12/building-c-8-0/

https://archive.codeplex.com/?p=asyncenum

原始答案

您需要使用IObservable<BlobItem>而不是IEnumerable<BlobItem>在这种情况下。至少在内部,取决于你实际如何调用 GetFiles .

这个问题有一些很好的解释,您应该研究一下:

How to yield return item when doing Task.WhenAny

或者corresponding blog post对于已接受的答案。

旁注:您可能需要使用参数 useFlatBlobListing=true对于 ListBlobsSegmentedAsync而不是手动执行递归代码。

一些快速代码描述了它的外观(未经测试或任何东西)

public IEnumerable<BlobItem> GetFilesAsEnumerable(CloudBlobContainer container, string directoryName, bool recursive)
{
return GetFiles(container, directoryName, recursive).ToEnumerable();
}

public IObservable<BlobItem> GetFiles(CloudBlobContainer container, string directoryName, bool recursive)
{
return Observable.Create<BlobItem>(async obs =>
{
BlobContinuationToken continuationToken = null;

do
{
var response = await container.GetDirectoryReference(directoryName).ListBlobsSegmentedAsync(/*useFlatBlobListing*/ recursive, BlobListingDetails.None, 100, continuationToken, null, null);

continuationToken = response.ContinuationToken;
foreach (var item in response.Results)
{
// Only required if recursive == false
if (item.GetType() != typeof(CloudBlobDirectory))
obs.OnNext(new BlobItem(item));
}
}
while (continuationToken != null);
});
}

关于c# - 使用 yield 来推迟 Azure blob 存储调用 - c#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52744608/

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