簡體   English   中英

將異步上傳到Azure Blob Storage永遠不會返回

[英]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.WaitTask.Wait等)。 如果要完成任務需要阻塞線程,則會發生死鎖。

我在博客上詳細解釋了這種情況 ,但其主旨是:

  • 默認情況下, await將捕獲“上下文”並使用它來恢復async方法。
  • 如果此代碼在ASP.NET請求上下文中執行,則此“上下文”是ASP.NET SynchronizationContext ; 如果此代碼在UI線程中執行,則此“上下文”是UI SynchronizationContext
  • ASP.NET SynchronizationContext和UI SynchronizationContext只允許其中的一個線程。

因此,當調用代碼阻塞返回的Task ,它在該上下文中保持一個線程,阻止Task完成。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM