我需要检查 MVC Controller 操作中是否存在 blob,并且我尝试以异步方式执行此操作,但没有成功。
如果我同步进行检查,它工作正常并且我得到了期望的结果,代码是下一个:
public ActionResult Index(string id, string size)
{
string redirectUrl;
if (string.IsNullOrEmpty(assetBlobUrl)) assetBlobUrl = ConfigurationManager.AppSettings["AssetBlobUrl"];
if (!string.IsNullOrEmpty(assetBlobUrl))
{
bool blobExists = _blobExists(size, id);
if (blobExists)
{
redirectUrl = string.Format(assetBlobUrl, size, id);
return new PermanentRedirectResult(redirectUrl);
}
}
return ResponseImageNotFound();
}
private bool _blobExists(string size, string assetId)
{
var container = serviceClient.GetContainerReference("images");
CloudBlockBlob blockBlob = container.GetBlockBlobReference(size + "/" + assetId + ".jpg");
bool checkBlobExists = blockBlob.Exists();
return checkBlobExists;
}
异步(不工作)版本是下一个:
public ActionResult Index(string id, string size)
{
string redirectUrl;
if (string.IsNullOrEmpty(assetBlobUrl)) assetBlobUrl = ConfigurationManager.AppSettings["AssetBlobUrl"];
if (!string.IsNullOrEmpty(assetBlobUrl))
{
bool blobExists = _blobExists(size, id).Result;
if (blobExists)
{
redirectUrl = string.Format(assetBlobUrl, size, id);
return new PermanentRedirectResult(redirectUrl);
}
}
return ResponseImageNotFound();
}
private async Task<bool> _blobExists(string size, string assetId)
{
bool blobExists = await container.GetBlockBlobReference(size + "/" + assetId + ".jpg").ExistsAsync();
return blobExists;
}
但这最后一种方式使网络持续加载,并且 ExistsAsync 行永远不会完成,因此永远不会命中下一个返回。
有什么帮助吗?
谢谢。
最佳答案
问题出在调用 .Result
,这通常是一种不好的做法,因为它是可以避免的。
当方法 _blobExists
它的await
吗? ,它消失,执行任务,然后尝试返回并继续。问题是您之前调用 .Result
已阻塞线程,因为它正在等待 _blobExists
完成获取 Result
。所以_blobExists
wait 正在等待线程空闲,以便它可以继续运行该方法并返回结果。
这意味着您最终会遇到死锁情况,两者都在等待对方。
幸运的是,我们可以将 Controller 操作定义为异步,因此将方法签名更改为:
public async Task<ActionResult> Index(string id, string size)
应该修复它。
但是您仍然需要小心,如果您不使用 .NET Core,那么您应该指定您不需要相同的同步上下文,否则问题仍然可能发生,方法是输入 .ConfigureAwait(false)
在您的await
上线。
关于c# Azure MVC 检查 Controller 调用.Result 是否存在 blob,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55238737/