Azure downloadtostreamasync方法挂起

时间:2015-02-15 12:54:49

标签: c# asynchronous azure-storage azure-storage-blobs asp.net-4.5

这是有问题的代码

    public async static Task<MemoryStream> AsyncReadBlob(string identifier)
    {
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageString);
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
        CloudBlobContainer container = blobClient.GetContainerReference(containerName);
        MemoryStream memstream = new MemoryStream();
        CloudBlockBlob blockBlob = container.GetBlockBlobReference(identifier);
        await blockBlob.DownloadToStreamAsync(memstream);
        return memstream;
    }

基本上,如果我替换

,代码运行完全正常

await blockBlob.DownloadToStreamAsync(memstream)

blockblob.DownloadToStream(memstream)

blockblob.DownloadToStreamAsync(memstream).wait()

但是当我把它变为异步时,&#34;下载到流#34;步骤永远不会完成我也尝试过使用DownloadToStreamBegin()然后等待它完成,但它再也没有完成。

它不起作用,因为它是静态方法吗?或者是因为它的记忆流正在从记忆中解除引用?

我使用的是asp.net 4.5,所有编译都正确,不会抛出任何解释器错误或异常。

非常感谢任何帮助

2 个答案:

答案 0 :(得分:17)

简短版本......使用:

 await blockBlob.DownloadToStreamAsync(memstream).ConfigureAwait(false);

长版:

当您等待C#中的任务时,任务调度程序将尝试在调用原始等待的同一线程中执行await之后的代码块。

问题在于,在某些情况下(现在无法回想起特定情况),ASP.NET线程调度程序将在等待任务返回时阻塞该线程。当任务返回时,任务阻止等待原始线程被释放,而线程被阻塞等待任务结束。所以你结束了僵局。

ConfigureAwait允许您停用该行为。

答案 1 :(得分:4)

您的代码几乎肯定是从Task<T>.Result进一步调用Task.WaitAsyncReadBlob调用堆栈,正是此阻塞代码导致死锁。我更详细地描述了这种情况on my blog

正确的解决方案是用Result替换所有Waitawait来电。