【发布时间】:2014-11-29 16:16:39
【问题描述】:
如何在 lambda 表达式中正确使用 async/await 关键字?这是代码:
public async Task<IHttpActionResult> GetUsers() {
var query = await _db.Users.ToListAsync();
var users = query.Select(async u => new
{
FirstName = u.FirstName,
LastName = u.LastName,
IsGeek = await _userManager.IsInRoleAsync(u.Id, "Geek")
});
return Ok(users);
}
正如你所看到的,这段代码在 webapi 控制器中运行,它编译没有任何错误,问题是它需要一个 extra await 某处,因为这个动作永远不会重新运行。
注意_db 和_usermanager 是应用程序的DbContext 和UserManager。
谢谢。
更新:
这个等效的代码永远不会失败(但它并不优雅:():
var query = await _db.Users.ToListAsync();
var users = new List<object>();
foreach (var u in query)
{
bool IsGeek = await _userManager.IsInRoleAsync(u.Id, "IsGeek");
users.Add( new {
FirstName = u.FirstName,
LastName = u.LastName,
IsGeek= IsGeek
});
}
return Ok(users);
【问题讨论】:
-
这可能永远不会返回,因为您正在某个地方同步等待。经典的 ASP.NET 死锁。也许在用户管理器中?
-
@usr 我不这么认为,
_usermanager继承自 AspNet.IdentityUserManager。 -
“它需要在某个地方额外等待”——你的意思是什么?为什么添加
await会改善情况?至于“永不返回”,不清楚你是如何称呼它的,但如果调用者是awaiting,那么方法中唯一可以设置卡住的两个地方是对ToListAsync()的调用和调用到Ok()。您的第一步是在调试器中观察执行情况并查看执行情况,然后准确追踪代码在该点的位置(即实际等待未返回的调用是什么)。 -
好的,那可能是正确的。你怎么知道这个动作永远不会返回?当您暂停调试器时,是否有线程在某个有意义的调用堆栈中等待?当您单步调试调试器时,它会挂在哪里?
-
@usr 我正在尝试使用 ajax 调用和提琴手,都没有回来。
标签: c# linq lambda async-await asp.net-web-api