异步方法不返回asp.net mvc 4

Bj *_*icz 8 c# asp.net asp.net-mvc asynchronous

我遇到了我实现的异步方法的问题.该方法基本上对资源进行HttpRequest,并在请求成功时反序列化字符串.我为该方法编写了一个测试,它可以工作.但是当我从控制器调用它时,该方法永远不会返回?

    public async Task<IEnumerable<T>> Get()
    {
        try
        {
            var resourceSegmentUri = new Uri(_uri, UriKind.Relative);

            var response = await _client.GetAsync(resourceSegmentUri);

            if (response.IsSuccessStatusCode)
            {
                var submission = await response.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<IEnumerable<T>>(submission);
            }

            if (response.Content != null)
            {
                var message = response.Content.ReadAsStringAsync();
                throw new WebException(message.Result, (WebExceptionStatus)response.StatusCode);
            }

        }
        catch (WebException e)
        {
            Logger.Error("GET Request failed with status: {0}", e.Status);
            throw;
        }

        throw new Exception();
    }
Run Code Online (Sandbox Code Playgroud)

永不返回的代码:

public ActionResult Index()
{
   var api = new Api();
   var test = api.Get().Result; //Never returns
   return View();
}
Run Code Online (Sandbox Code Playgroud)

有效的测试:

[Test]
public void GetShouldReturnIfSuccessfulRequest()
{
    var api = new Api();
    var submission = api.Get();

    Console.WriteLine(JsonConvert.SerializeObject(submission));
    Assert.NotNull(submission);
}
Run Code Online (Sandbox Code Playgroud)

有谁知道这个问题?

Nic*_*ler 12

你有一个死锁,因为你正在调用.Result你的控制器动作.

如果您使用,async/await那么您也必须使用异步操作.

所以这样的事情应该解决它:

public async Task<ActionResult> Index()
{
  var api = new Api();
  var test = await api.Get(); // Should return
}
Run Code Online (Sandbox Code Playgroud)

这里有一篇关于此的综合文章:在ASP.NET MVC 4中使用异步方法

  • +1.@BjBlazkowicz:我在[我的博客](http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html)和我[最近的MSDN文章]中解释了死锁的原因(http://msdn.microsoft.com/en-us/magazine/jj991977.aspx). (6认同)
  • @BjBlazkowicz然后最好的选择是使服务方法也是"异步".如果你开始使用`async/await`,你必须在调用堆栈中一直使用它. (2认同)