c# Azure MVC 从控制器调用 .Result 检查 blob 是不是存在

Posted

技术标签:

【中文标题】c# Azure MVC 从控制器调用 .Result 检查 blob 是不是存在【英文标题】:c# Azure MVC check if blob exists from controller Calling .Resultc# Azure MVC 从控制器调用 .Result 检查 blob 是否存在 【发布时间】:2019-08-09 20:19:27 【问题描述】:

我需要检查 MVC 控制器操作中是否存在 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 通常是个坏主意。你能把你的方法改成public async Task&lt;ActionResult&gt; Index,然后用await _blobExists...代替.Result吗? 你就是那个男人@NibblyPig!现在它可以工作了,非常感谢你,如果你把它写成答案,我会把它标记为正确的。 【参考方案1】:

问题在于调用.Result,这通常是一种不好的做法,因为它可以避免。

当方法_blobExists 执行它的await 时,它会消失,执行任务,然后尝试返回并继续。问题是您之前对.Result 的调用已阻塞线程,因为它正在等待_blobExists 完成获取Result。所以_blobExists await 正在等待线程空闲,以便它可以继续运行该方法并返回您的结果。

这意味着您最终会遇到死锁情况,双方都在等待对方。

幸运的是,我们可以将控制器操作定义为异步,因此将方法签名更改为:

public async Task&lt;ActionResult&gt; Index(string id, string size) 应该修复它。

但是您仍然需要小心,如果您不使用 .NET Core,那么您应该指定您不需要相同的同步上下文,否则问题仍然可能发生,方法是将 .ConfigureAwait(false) 放在您的 @987654330 上@线。

【讨论】:

以上是关于c# Azure MVC 从控制器调用 .Result 检查 blob 是不是存在的主要内容,如果未能解决你的问题,请参考以下文章

使用 C# 以编程方式向 MVC 控制器验证 Azure Ad/OpenId 并获取重定向 uri

C# MVC Web 应用服务连接到 Azure 存储 Blob

从控制器获取结果,但在 MVC5 和 C# 中,ajax 调用获取错误而不是成功

C# MVC 架构,我应该从 MODEL 还是 CONTROLLER 调用存储过程

从 Azure 中托管的 ASP.NET Core 5.0 MVC 站点调用 API/服务的间歇性套接字异常

是否可以使用托管标识从 C# 控制台代码连接 Azure 文件共享(存储帐户)