使用 .NET 4.5 异步将 Azure blob 异步下载到字符串,等待 [英] Asynchronous download of an Azure blob to string with .NET 4.5 async, await
问题描述
我正在尝试使用 .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?
我希望得到一些额外的说明:
GetContainerReference
和GetBlockBlobReference
不需要异步,因为它们还没有联系服务器,对吧?
GetContainerReference
andGetBlockBlobReference
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?
它没有(也不应该).Stream
是 async
编程的一个不寻常的例子.通常,如果有 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屋!