代码之家  ›  专栏  ›  技术社区  ›  Rob

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

  •  1
  • Rob  · 技术社区  · 7 年前

    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;
    }
    

    我不喜欢上面的代码,因为我遍历了所有文件并添加到结果中,直到取消标记为null。所以基本上,去拿所有的东西,然后停下来再回来。

    我不太熟悉使用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;
    
    1 回复  |  直到 7 年前
        1
  •  4
  •   Alex AIT    7 年前

    编辑2018-11-15 从开始 C#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);
            });
    }
    
    推荐文章