我需要检查MVC控制器动作中是否存在斑点,而我正在尝试以异步方式进行操作,但没有成功。
如果我同步执行检查,则可以正常工作,并且可以得到所需的结果,并且代码如下:
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;
}
但是,这是Web继续加载的最后一种方式,与ExistsAsync的连接永远不会结束,因此永远不会产生下一个返回。
有帮助吗?
谢谢。
答案 0 :(得分:1)
问题出在调用.Result
上,这通常是一个坏习惯,因为可以避免。
方法_blobExists
执行其await
时,它消失了,执行任务,然后尝试返回并继续。问题是您先前对.Result
的调用已阻塞线程,因为它正在等待_blobExists
完成获取Result
的操作。因此_blobExists
等待正在等待线程释放,以便它可以继续运行该方法并返回结果。
这意味着您最终将陷入僵局,并且两者都在等待对方。
幸运的是,我们可以将控制器动作定义为异步动作,因此将方法签名更改为:
public async Task<ActionResult> Index(string id, string size)
应该解决它。
但是,仍然需要注意,如果您不使用.NET Core,则应指定不需要相同的同步上下文,否则,可以通过在您的计算机上放置.ConfigureAwait(false)
来解决问题await
行。