async/await 的一些知識 (死鎖問題)

博文


案例一

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

相關文章
相關標籤/搜索