使用 .NET 4.5 异步将 Azure blob 异步下载到字符串,等待 [英] Asynchronous download of an Azure blob to string with .NET 4.5 async, await

查看:25
本文介绍了使用 .NET 4.5 异步将 Azure blob 异步下载到字符串,等待的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 .NET 4.5 async & 实现 完全异步 blob 下载等待.

I'm trying to implement a fully asynchronous blob download with .NET 4.5 async & await.

假设整个 blob 可以一次性放入内存,并且我们希望将其保存在 string 中.

Let's assume the entire blob can fit in memory at once, and we want to hold it in a string.

代码:

public async Task<string> DownloadTextAsync(ICloudBlob blob)
{
    using (Stream memoryStream = new MemoryStream())
    {
        IAsyncResult asyncResult = blob.BeginDownloadToStream(memoryStream, null, null);
        await Task.Factory.FromAsync(asyncResult, (r) => { blob.EndDownloadToStream(r); });
        memoryStream.Position = 0;

        using (StreamReader streamReader = new StreamReader(memoryStream))
        {
            // is this good enough?
            return streamReader.ReadToEnd();

            // or do we need this?
            return await streamReader.ReadToEndAsync();
        }
    }
}

用法:

CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageAccountConnectionString"));
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("container1");
CloudBlockBlob blockBlob = container.GetBlockBlobReference("blob1.txt");

string text = await DownloadTextAsync(blockBlob);

这段代码是否正确并且确实是完全异步的?你会以不同的方式实施吗?

Is this code correct and this is indeed fully asynchronous? Would you implement this differently?

我希望得到一些额外的说明:

  1. GetContainerReferenceGetBlockBlobReference 不需要异步,因为它们还没有联系服务器,对吧?

  1. GetContainerReference and GetBlockBlobReference don't need to be async since they don't contact the server yet, right?

streamReader.ReadToEnd 是否需要异步?

我对 BeginDownloadToStream 的作用有点困惑.. 当 EndDownloadToStream 被调用时,我的内存流是否全部em>里面的数据?还是流只打开预读?

I'm a little confused about what BeginDownloadToStream does.. by the time EndDownloadToStream is called, does my memory stream have all the data inside? or is the stream only open pre read?

更新:(从 Storage 2.1.0.0 RC 开始)

现在原生支持异步.

CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageAccountConnectionString"));
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("container1");
CloudBlockBlob blockBlob = container.GetBlockBlobReference("blob1.txt");

string text = await blockBlob.DownloadTextAsync();

推荐答案

这段代码是否正确并且确实是完全异步的?

Is this code correct and this is indeed fully asynchronous?

是的.

你会以不同的方式实施吗?

Would you implement this differently?

是的.特别是,如果您传入 Begin/End 方法对,而不是传入现有的 <代码>IAsyncResult.像这样:

Yes. In particular, the TaskFactory.FromAsync wrappers are much more efficient if you pass in a Begin/End method pair instead of passing in an existing IAsyncResult. Like this:

await Task.Factory.FromAsync(blob.BeginDownloadToStream,
    blob.EndDownloadToStream, memoryStream, null);

我也更喜欢将它们包装成单独的扩展方法,这样我就可以这样称呼它:

I also prefer to wrap these up into separate extension methods so I can call it like this:

await blog.DownloadToStreamAsync(memoryStream);

请注意,客户端库的下一个版本(2.1,目前在 RC 中)将具有 async-ready 方法,即 DownloadToStreamAsync.

Note that the next version of the client libraries (2.1, currently in RC) will have async-ready methods, i.e., DownloadToStreamAsync.

GetContainerReference 和 GetBlockBlobReference 不需要异步,因为它们还没有联系服务器,对吧?

GetContainerReference and GetBlockBlobReference don't need to be async since they don't contact the server yet, right?

正确.

streamReader.ReadToEnd 是否需要异步?

Does streamReader.ReadToEnd need to be async or not?

它没有(也不应该).Streamasync 编程的一个不寻常的例子.通常,如果有 async 方法,那么您应该在 async 代码中使用它,但该指南不适用于 Stream 类型.原因是基本的 Stream 类不知道它的实现是同步的还是异步的,所以它假设它是同步的,并且默认情况下只会通过在后台做同步工作来伪造它的异步操作线.真正的异步流(例如,NetworkStream)会覆盖它并提供真正的异步操作.同步流(例如,MemoryStream)保持这种默认行为.

It does not (and should not). Stream is a bit of an unusual case with async programming. Usually, if there's an async method then you should use it in your async code, but that guideline doesn't hold for Stream types. The reason is that the base Stream class doesn't know whether its implementation is synchronous or asynchronous, so it assumes that it's synchronous and by default will fake its asynchronous operations by just doing the synchronous work on a background thread. Truly asynchronous streams (e.g., NetworkStream) override this and provide true asynchronous operations. Synchronous streams (e.g., MemoryStream) keep this default behavior.

所以您不想想在 MemoryStream 上调用 ReadToEndAsync.

So you don't want to call ReadToEndAsync on a MemoryStream.

我对 BeginDownloadToStream 的作用有点困惑.. 调用 EndDownloadToStream 时,我的内存流是否包含所有数据?

I'm a little confused about what BeginDownloadToStream does.. by the time EndDownloadToStream is called, does my memory stream have all the data inside?

是的.操作为DownloadToStream;它将一个 blob 下载到一个流中.由于您正在将 blob 下载到 MemoryStream 中,因此在此操作完成时,blob 已完全在内存中.

Yes. The operation is DownloadToStream; that it, it downloads a blob into a stream. Since you are downloading a blob into a MemoryStream, the blob is entirely in memory by the time this operation completes.

这篇关于使用 .NET 4.5 异步将 Azure blob 异步下载到字符串,等待的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆