public List<BSubject> BSubjectList {get; set; }
public async Task<List<BSubject>> BSDetails(Guid id)
{
BSubjectList= await DC.Set<BSubject>().Where(e => e.BId == id)
.Include(e => e.PAnswers).ThenInclude(a => a.EAnswer).OrderBy(e => e.SType).ThenBy(e => e.EPBSNO).AsNoTracking().ToListAsync();
return BSubjectList;
}
public async Task<ActionResult> EExamAsync()
{
//...省略...vm.Entity.ID逻辑获取到ID使用
await BSDetails(vm.Entity.ID);
return PartialView(vm);
}
代码1 以上BSDetails 是有返回值的,直接赋值BSubjectlist,没有必要再返回值
现在我想优化为代码2
public List<BSubject> BSubjectList {get; set; }
public void BSDetails(Guid id)
{
BSubjectList= DC.Set<BSubject>().Where(e => e.BId == id)
.Include(e => e.PAnswers).ThenInclude(a => a.EAnswer).OrderBy(e => e.SType).ThenBy(e => e.EPBSNO).AsNoTracking().ToList();
}
public async Task<ActionResult> EExamAsync()
{
//...省略...vm.Entity.ID逻辑获取到ID使用
BSDetails(vm.Entity.ID);
return PartialView(vm);
}
这样优化VOID使用,系统又没有使用异步,是不是性能稳定性还不如之前的代码1,请专家高手帮忙分析指导一下,谢谢
理论上 同步比异步的性能可能要高那么几ns. 但是同步带来的资源利用率要比异步低不少.
假设在web环境中, 大量调用BSDetails 这个方法. 异步将获得比同步好得多的TPS.
原因: 像这种数据库查询, 系统绝大部分时间都是在IO等待. 所以异步比同步有优势的多.
感谢您的回复,那还是维持代码1更有优势吗?异步可以,但是这个BSDetails 方法感觉不需要return ,view页面里 直接使用BSubjectList显示数据库内容的
@makoshen: 可以不返回Task<T>, 至少得返回 Task. 并且caller必须await.
假设BSDetails返回void, 在调用之后, task还没有完成. 意味着BSubjectList 没有数据. view里面怎么用呢
@czd890:嗯嗯,现在代码1 控制器caller时候 就有 await的.您说的 至少得返回 Task,这个方法怎么写?
@makoshen:
public async Task<List<BSubject>> BSDetails(Guid id)
=>
public async Task BSDetails(Guid id)
@czd890: 谢谢您,这样写,在caller await 之后 我是否需要再加个判断BSubjectList.any() 没有数据无法VIEW页面?
@makoshen: 光从代码来讲是的, 不光.Any() 最好加上!=null
从设计(api设计, 软件工程)来说, 这不是一个很好的代码.
假设方法BSDetails所在的class是一个有状态的model. 或者说为了重用BSubjectList.
大概可以改成(具体问题具体分析哈. 不用刻意理解)
private _BSubjectList;
public async Task<IReadOnlyCollection<BSubject>> GetBSDetailsAsync(Guid id)
{
if(_BSubjectList == null) _BSubjectList= await ....;
return _BSubjectList;
}
@czd890: 假设方法BSDetails所在的class是一个有状态的model.是不是假设说 这个class在读取数据库显示到VIEW页面的时候,若有人同时在修改这个CLASS这个ID数据的时候,就会有异常发生?
@makoshen: 是呀, 假设这个class 是共享的, 那么
user1 BSDetails(1)
user2 BSDetails(2)
user1 view() 应该显示1的数据,但是有可能变成2的
@czd890: 感谢提醒,这个绝对要拒绝这样的情况发生,500个用户,以每个用户的ID,必须只能显示自己的信息内容,而且这500个人会在同一个时间点登录系统,调用这个方法,显示自己的内容。user1 view() 应该显示1的数据,但是有可能变成2的,怎么拒绝这个情况发生呢?
@czd890: private List<BSubject> _BSubjectList;
public async Task<IReadOnlyCollection<BSubject>> GetBSDetailsAsync(Guid id)
{
if(_BSubjectList == null) _BSubjectList= await DC.Set<BSubject>().Where(e => e.BId == id)
.Include(e => e.PAnswers).ThenInclude(a => a.EAnswer).OrderBy(e => e.SType).ThenBy(e => e.EPBSNO).AsNoTracking().ToListAsync();
return _BSubjectList;
}
在调用这个方法的控制器里
public async Task<ActionResult> EExamAsync()
{
//这里怎么赋值给什么?在VIEW页面里调用显示呢?
await GetBSDetailsAsync(vm.Entity.ID);
return PartialView(vm);
}
@makoshen:
Task<IReadOnlyCollection<BSubject>> GetBSDetailsAsync(Guid id)
var data = await GetBSDetailsAsync(vm.Entity.ID);
return PartialView(data);