蔚蓝色的斑点异步下载到字符串.NET 4.5异步,等待 [英] Asynchronous download of an Azure blob to string with .NET 4.5 async, await

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

问题描述

我想实现的完全异步的blob与.NET 4.5异步和放大器下载;等待着。

让我们假设整个BLOB可以容纳在内存中一次,我们要拿着它在字符串

code:

 公共异步任务<串GT; DownloadTextAsync(ICloudBlob BLOB)
{
    使用(流的MemoryStream =新的MemoryStream())
    {
        IAsyncResult的asyncResult = blob.BeginDownloadToStream(MemoryStream的,NULL,NULL);
        等待Task.Factory.FromAsync(asyncResult,(R)=> {blob.EndDownloadToStream(R);});
        memoryStream.Position = 0;        使用(StreamReader的StreamReader的=新的StreamReader(MemoryStream的))
        {
            //这是不够好?
            返回streamReader.ReadToEnd();            //还是我们需要这个?
            返回等待streamReader.ReadToEndAsync();
        }
    }
}

用法:

  CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting(StorageAccountConnectionString));
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer容器= blobClient.GetContainerReference(container1);
CloudBlockBlob blockBlob = container.GetBlockBlobReference(blob1.txt);字符串文本=等待DownloadTextAsync(blockBlob);

这是code正确的,这确实是完全异步?你会不同的方式实现这一点?

我倒是AP preciate一些额外的说明:


  1. GetContainerReference GetBlockBlobReference 不必是异步,因为他们不联系服务器然而,对吧?


  2. 确实 streamReader.ReadToEnd 必须是异步或不?


  3. 我有点困惑的时候是什么 BeginDownloadToStream 确实.. EndDownloadToStream 被称为,我的内存流有内部的所有的数据?或只开放pre读取流?


更新:(作为存储2.1.0.0 RC)

异步现在支持原生。

  CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting(StorageAccountConnectionString));
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer容器= blobClient.GetContainerReference(container1);
CloudBlockBlob blockBlob = container.GetBlockBlobReference(blob1.txt);字符串文本=等待blockBlob.DownloadTextAsync();


解决方案

  

这是code正确的,这确实是完全异步的?



  

你不同的方式实现这一点?


是的。尤其是, TaskFactory.FromAsync 包装是更有效的,如果你在一个通过开始 / 结束方法对强似在现有的的IAsyncResult 。像这样的:

 等待Task.Factory.FromAsync(blob.BeginDownloadToStream,
    blob.EndDownloadToStream,MemoryStream的,NULL);

我也preFER把它们包装成单独的扩展方法,所以我可以这样调用它:

 等待blog.DownloadToStreamAsync(MemoryStream的);

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


  

GetContainerReference和GetBlockBlobReference不必是异步,因为它们不在服务器联系呢,对吧?


正确的。


  

请问streamReader.ReadToEnd都需要进行异步或不?


它没有(也不应该)。 是有点不寻常的情况下与异步节目。通常情况下,如果有一个异步方法,那么你应该在你的异步 code使用它,但该准则没有按T持有类型。其原因是,该基地类不知道它的实现是同步的还是异步的,因此它假定它是同步的,在默认情况下将假冒其通过只是在做异步操作在后台线程同步工作。真正的异步流(例如,的NetworkStream )覆盖此,并提供真正的异步操作。同步流(例如,的MemoryStream )保持这个默认的行为。

所以你的的要调用 ReadToEndAsync 的MemoryStream


  

我有点无所适从BeginDownloadToStream由EndDownloadToStream被调用的时候呢..,做我的记忆流里面有所有的数据?


是的。操作 DownloadToStream ;它,它会下载一个blob成流。既然你正在下载一个blob成的MemoryStream ,团块完全是在内存中完成此操作的时间。

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

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

Code:

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

Usage:

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?

I'd appreciate some extra clarifications:

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

  2. Does streamReader.ReadToEnd need to be async or not?

  3. 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?

Update: (as of Storage 2.1.0.0 RC)

Async now supported natively.

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?

Yes.

Would you implement this differently?

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

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

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

Correct.

Does streamReader.ReadToEnd need to be async or not?

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.

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

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

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异步,等待的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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