我非常擅长为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?
由于
埃里克
答案 0 :(得分:1)
您的问题几乎可以肯定在此代码中:
在我的viewmodel的构造函数中调用LoadAllEntities。
我在博客上详细解释了why this deadlock happens。它与ReadAsAsync
或IQueryable
没有任何关系。它与在异步任务上调用Wait
或Result
有关。
总结:
async
方法返回的任务仅在该方法完成时才完成。await
会捕获“上下文”并使用该“上下文”来恢复async
方法。AspNetSynchronizationContext
的一个实例,它一次只允许一个线程。Wait
/ Result
时,它将阻止该线程(仍在ASP.NET请求上下文中),等待任务完成。await
准备好恢复该方法时,它会在捕获的上下文中这样做,并等待上下文自由。await
无法在上下文空闲之前完成该方法,并且等待该方法完成的线程正在使用该上下文,因此最终会出现死锁。解决这个问题的正确方法是不阻止异步代码;请改用await
。这个原则称为“async all the way”,并在我的MSDN文章中描述了异步最佳实践。由于您尝试从构造函数中调用异步代码,因此您也可以在async constructors上找到我的博客文章,这有助于解释一些替代方法。