HttpClient ReadAsAsync <iqueryable <t>&gt;永远不会回来

时间:2016-06-16 11:13:18

标签: c# entity-framework asp.net-web-api iqueryable

我非常擅长为asp.net编写控制器并且我试图返回IQueryable,但我似乎无法接受内容返回的调用。

这是我的控制者:

    // GET: api/RumsaRooms
    [EnableQuery]
    public IQueryable<RumsaRoom> GetRooms()
    {
        return db.Rooms;

    }

这是我的客户电话:

    public async Task<IQueryable<T>> GetAllOf<T>()
    {
        var typeName = typeof(T).Name;



        var result = await _client.GetAsync($"api/{typeName}");

        if (!result.IsSuccessStatusCode)
        {
            var exception = await result.Content.ReadAsStringAsync();


        }
        //This method never returns
        var rooms = await result.Content.ReadAsAsync<IQueryable<T>>(); 

        return rooms;



    }

我在connectionstring中启用了多个activeactiveresultsets。 StatusCode是200.

GetAllOf()的方法如下所示:

    private async Task<bool> LoadEntities()
    {
        var rooms = (await _rumsaClient.GetAllOf<RumsaRoom>()).ToList();

        RoomsCollection = new ObservableCollection<RumsaRoom>(rooms);


        return true;
    }

在我的viewmodel的构造函数中调用LoadAllEntities。 如果我改变对此的调用,它可以工作:

var rooms = await result.Content.ReadAsAsync<List<T>>();

是否无法将ReadAsAsync发送到IQueryable?

由于

埃里克

1 个答案:

答案 0 :(得分:1)

您的问题几乎可以肯定在此代码中:

  

在我的viewmodel的构造函数中调用LoadAllEntities。

我在博客上详细解释了why this deadlock happens。它与ReadAsAsyncIQueryable没有任何关系。它与在异步任务上调用WaitResult有关。

总结:

  • async方法返回的任务仅在该方法完成时才完成。
  • 默认情况下,
  • await会捕获“上下文”并使用该“上下文”来恢复async方法。
  • 在ASP.NET上,这个“上下文”是AspNetSynchronizationContext的一个实例,它一次只允许一个线程。
  • 当代码调用Wait / Result时,它将阻止该线程(仍在ASP.NET请求上下文中),等待任务完成。
  • await准备好恢复该方法时,它会在捕获的上下文中这样做,并等待上下文自由。
  • 由于await无法在上下文空闲之前完成该方法,并且等待该方法完成的线程正在使用该上下文,因此最终会出现死锁。

解决这个问题的正确方法是不阻止异步代码;请改用await。这个原则称为“async all the way”,并在我的MSDN文章中描述了异步最佳实践。由于您尝试从构造函数中调用异步代码,因此您也可以在async constructors上找到我的博客文章,这有助于解释一些替代方法。

相关问题