我正在尝试使用异步方法将文件上传到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 Storage Explorer查看其内容),但是该过程似乎没有移至下一行(这将是第一条日志记录消息)。
如果我将所有异步调用都切换为它们的非异步对应项,则代码将按预期工作。
谁能解释为什么UploadFromByteArrayAsync
似乎没有回来?
更新:我想我会添加一些有关上下文的更多信息,以防它有所帮助。
此代码是从Web API方法中调用的。有问题的控制器没有异步代码,除了调用存储库方法外,无所作为。在调用与Blob存储接口的类之前,存储库方法会更新SQL DB-同样,所有这些都是非异步代码。
这个面向Blob存储的类具有非异步方法,除了使用.Wait()
或调用它们的异步等效项外,其他操作无济于事.Result
。
在有问题的情况下,第二阶段的存储库正在调用非异步版本,因此上述代码本质上是通过调用的.Wait()
。
在上述代码之前,此HTTP请求中从进入Web API控制器的位置开始,没有其他异步调用。
该错误是几乎可以肯定进一步您的通话栈,其中一些方法在返回的任务阻塞(如Task<T>.Result
,Task.Wait
等)。如果完成任务需要阻塞的线程,则会死锁。
我在博客上完整地解释了这种情况,但是要点是:
await
默认情况下将捕获一个“上下文”,并使用它来恢复该async
方法。SynchronizationContext
;如果此代码在UI线程中执行,则此“上下文”是UI SynchronizationContext
。SynchronizationContext
和UI一次SynchronizationContext
只允许一个线程。因此,当调用代码在return上阻塞时Task
,它将在该上下文中保留一个线程,从而阻止了该线程的Task
完成。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句