[英]Uploading async to Azure Blob Storage never returns
我正在尝试使用异步方法将文件上载到Azure blob存储,然后设置其元数据,但UploadFromByteArrayAsync
方法永远不会返回。
我有以下代码:
var connAzureBlob = ConfigurationManager.AppSettings["AzureBlobStorage"];
var storageAccount = CloudStorageAccount.Parse(connAzureBlob);
var blobClient = storageAccount.CreateCloudBlobClient();
var fileContainer = blobClient.GetContainerReference(ConfigurationManager.AppSettings["AzureBlobContainer"]);
if (!fileContainer.Exists())
{
await fileContainer.CreateAsync();
await fileContainer.SetPermissionsAsync(new BlobContainerPermissions {
PublicAccess = BlobContainerPublicAccessType.Blob
});
}
try
{
var fileBlob = fileContainer.GetBlockBlobReference(documentId.ToString());
await fileBlob.UploadFromByteArrayAsync(buffer, 0, buffer.Length);
Log.Info($"{nameof(SaveToBlobAsync)}: blob {documentId} uploaded.");
await fileBlob.FetchAttributesAsync();
fileBlob.Properties.ContentType = contentType;
fileBlob.Metadata["..."] = "...";
await fileBlob.SetMetadataAsync();
Log.Info($"{nameof(SaveToBlobAsync)}: {documentId} - metadata saved.");
}
catch (Exception exception)
{
Log.Error($"{nameof(SaveToBlobAsync)}: An exception was thrown while saving a file to a blob: ", exception);
throw;
}
使用上面的代码,我希望看到以下消息记录:
SaveToBlobAsync:blob 123已上传。
SaveToBlobAsync:123 - 保存元数据。
但这些从未出现过。
但是,blob似乎存储(我可以使用Azure存储资源管理器查看其内容),但该过程似乎没有移动到下一行(这将是第一个日志消息)。
如果我为非异步对应方切换所有异步调用,则代码按预期工作。
任何人都可以解释为什么UploadFromByteArrayAsync
似乎没有返回?
更新:我想我会添加一些关于上下文的更多信息,以防它有所帮助。
此代码是从Web API方法调用的。 有问题的控制器没有异步代码,除了调用存储库方法之外别无其他。 存储库方法在调用与blob存储接口的类之前更新SQL DB - 再次,所有这些都是非异步代码。
这个面向blob存储的类具有非异步方法,除了使用.Wait()
或.Result
调用它们的异步等效项之外别无其他。
在有问题的情况下,第二阶段的存储库调用非异步版本,因此上面的代码基本上是用.Wait()
调用的。
在上面的代码之前,此HTTP请求中没有其他异步调用,从它进入Web API的控制器。
错误几乎肯定会进一步上升到你的调用堆栈,其中某些方法阻止返回的任务(例如, Task<T>.Result
Task.Wait
, Task.Wait
等)。 如果要完成任务需要阻塞线程,则会发生死锁。
我在博客上详细解释了这种情况 ,但其主旨是:
await
将捕获“上下文”并使用它来恢复async
方法。 SynchronizationContext
; 如果此代码在UI线程中执行,则此“上下文”是UI SynchronizationContext
。 SynchronizationContext
和UI SynchronizationContext
只允许其中的一个线程。 因此,当调用代码阻塞返回的Task
,它在该上下文中保持一个线程,阻止Task
完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.