在getter中调用异步方法会引发异常

时间:2016-03-23 08:15:36

标签: c# asynchronous task-parallel-library

我已经构建了一个API端点来从中获取可用语言。在我的MVC应用程序中,我有一个帮助程序来获取语言异步。该方法定义如下:

public static async Task<Languages> GetLanguagesAsync()
{
    var apiResponse = await APIHelper.GetContentGetAsync("Languages").ConfigureAwait(false);
    return apiResponse.LanguagesDataModel;
}

在我的View中,我想将下拉列表绑定到用户可以选择的可用语言列表。

  

@ Html.DropDownListFor(m =&gt; m.Language,LanguageHelper.AvailableLanguages)

getter定义如下:

public static IEnumerable<SelectListItem<string>> AvailableLanguages
{
    get
    {
        var result = GetLanguagesAsync().Result;
        return new List<SelectListItem<string>>(result.Languages.Select(l => new SelectListItem<string> {Value = l.Key, Text = l.Value}));
    }
}

但是,我总是在第var result = GetLanguagesAsync().Result;行收到错误,这是here最受欢迎的答案。

抛出的异常是

  

此时无法启动异步操作。异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的某些事件中启动。如果在执行页面时发生此异常,请确保将页面标记为&lt;%@ Page Async =&#34; true&#34; %取代。此异常也可能表示尝试调用&#34; async void&#34;方法,在ASP.NET请求处理中通常不受支持。相反,异步方法应该返回一个Task,调用者应该等待它。

如上所述here,被叫操作标记为async

1 个答案:

答案 0 :(得分:1)

今天的Razor代码无法处理异步调用,即使您使用同步阻塞(is a design mistake)来封装这些调用。操作为async的事实并不重要,因为这是在操作完成后处理视图期间。

ASP.NET Core中添加了异步视图;但是,它应该仍然是一个不常见的用例。

一般来说,您的选择是:

  • 让助手同步“一直”;即,使用同步API调用而不是异步,并摆脱异步同步代码。
  • 将数据添加到视图模型中(可能作为常见VM基础的一部分)。

在这个具体案例中,我同意Panagiotis的意见,即每个应用程序只能加载一次这种不变的信息,而不是每次调用一次。在Lazy<T>内包装同步实现将是最简单的解决方案。