asp.net Web API 项目中的 Azure CloudBlockBlob.DownloadTextAsync() 从不 returns 但同样适用于控制台应用程序

Azure CloudBlockBlob.DownloadTextAsync() in asp.net Web API project never returns but same works in console application

我创建了一个 Asp.Net Web API 项目,它使用 Azure CloudBlockBlob 异步下载一些文本,但调用从未 returns.

我尝试 运行 控制台应用程序中的相同代码,它工作正常。

以下是有问题的代码:-

public async Task<string> DownloadTextAsync(IBlobRef blobRef, CancellationToken cancellationToken)
    {
        var container = this.GetContainerReference(blobRef);
        try
        {
            this.Logger.Log("Downloading " + blobRef.BlobName);
            return await container.GetBlockBlobReference(blobRef.BlobName).DownloadTextAsync();
        }
        catch (Microsoft.WindowsAzure.Storage.StorageException e)
        {
            if (e.RequestInformation.HttpStatusCode == 404)
                return null;
            Console.WriteLine("Error reading " + blobRef.BlobName + " " + e.Message);
            return null;
        }
    }

如果我在控制台应用程序或 asp.net 网络表单应用程序中 运行 使用相同的代码,那么它 运行 完全没问题。

如果我做错了什么,请提供帮助。

您几乎肯定会在调用堆栈的更上方调用 Task<T>.ResultTask.Wait。这会导致 common deadlock issue that I describe on my blog.

它死锁的原因是因为 await(默认情况下)将捕获当前的 "context" - 在这种情况下,ASP.NET 请求上下文。然后,当操作完成时,它将在该上下文中恢复 async 方法。但是,ASP.NET 请求上下文一次只允许一个线程进入。因此,如果 ASP.NET 请求上下文中有线程 blocked(例如,通过调用 Task.Wait),则 async 方法无法恢复执行await 完成。

它不会在控制台应用程序中死锁,因为控制台应用程序没有 "context"。在这种情况下,async 方法在线程池线程上恢复。

要解决此问题,请将对 ResultWait 的任何调用替换为 await,并允许 async 通过您的代码增长。有关详细信息,请参阅 my MSDN article on async best practices