在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線程