尽我所能,我一直选择异步。但是,我仍然无法使用不是为异步构建的ASP.NET Membership。结果,我对类似方法的调用string[] GetRolesForUser()
无法使用异步。
为了正确地建立角色,我依赖于来自各种来源的数据,因此我正在使用多个任务来并行获取数据:
public override string[] GetRolesForUser(string username) {
...
Task.WaitAll(taskAccounts, taskContracts, taskOtherContracts, taskMoreContracts, taskSomeProduct);
...
}
所有这些任务仅是使用实体框架从SQL Server数据库中获取数据。但是,最后一个任务(taskSomeProduct
)的引入导致了死锁,而其他方法都没有。
这是导致死锁的方法:
public async Task<int> SomeProduct(IEnumerable<string> ids) {
var q = from c in this.context.Contracts
join p in this.context.Products
on c.ProductId equals p.Id
where ids.Contains(c.Id)
select p.Code;
//Adding .ConfigureAwait(false) fixes the problem here
var codes = await q.ToListAsync();
var slotCount = codes .Sum(p => char.GetNumericValue(p, p.Length - 1));
return Convert.ToInt32(slotCount);
}
但是,此方法(看起来与所有其他方法非常相似)不会导致死锁:
public async Task<List<CustomAccount>> SomeAccounts(IEnumerable<string> ids) {
return await this.context.Accounts
.Where(o => ids.Contains(o.Id))
.ToListAsync()
.ToCustomAccountListAsync();
}
我不太确定导致死锁的一种方法是什么。最终,他们俩都在执行查询数据库的相同任务。添加ConfigureAwait(false)
一个方法确实可以解决问题,但是我不确定是什么与其他执行得很好的方法有什么区别。
编辑
这里是一些其他代码,为简洁起见,我最初省略了它们:
public static Task<List<CustomAccount>> ToCustomAccountListAsync(this Task<List<Account>> sqlObjectsTask) {
var sqlObjects = sqlObjectsTask.Result;
var customObjects = sqlObjects.Select(o => PopulateCustomAccount(o)).ToList();
return Task.FromResult<List<CustomAccount>>(customObjects);
}
该PopulateCustomAccount
方法CustomAccount
仅从数据库Account
对象返回一个对象。
在ToCustomAccountListAsync
你打Task.Result
。那是一个经典的僵局。使用await
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句