在ABP.Zero最近的一次更新中,有这样的修改:
解释的缘由是:
在一个不是异步的方法中返回一个Task, 通常来讲是没有问题的,可是当这段代码被using包裹时,using可能在Task执行完成前就释放。因而租户ID会被恢复为旧值,而再也不是null,致使数据写入数据库时tenantId不对。html
async Task TestAsync() { await Task.Delay(1000); }
andgit
Task TestAsync() { return Task.Delay(1000); }
前者相似于Task.Delay(1000).ContinueWith(() = {}),后者就是通常的 Task.Delay(1000)。github
static async Task TestAsync() { await Task.Delay(1000); } private void button1_Click(object sender, EventArgs e) { TestAsync().Wait(); // dead-lock here }
改为下面这种 non-async版本就不会死锁了(但放弃了异步)数据库
static Task TestAsync() { return Task.Delay(1000); }
或将上层方法也改成异步(更好的方案)异步
private async void button1_Click(object sender, EventArgs e) { await TestAsync(); }
不管是UI context 仍是 ASP.NET request context都不会和某个特定的线程绑定,可是在同一时间,只有一个线程能够访问它。async
上层方法也改用异步后,则全部等待都是异步等待,上层方法也不会阻塞context线程