簡體   English   中英

盡管ConfigureAwait仍然ASP.NET死鎖(false)

[英]ASP.NET deadlock despite ConfigureAwait(false)

編輯:我現在通過簡單地將按鈕單擊處理程序標記為異步無效並等待任務來解決了該問題。 我以為WebForms不能以任何方式處理異步,除非與RegisterAsyncTask一起使用。 盡管這解決了我的問題,但我仍然對為什么死鎖下面的代碼感興趣,因為它與我目前對異步C#代碼如何工作的理解背道而馳,因此仍然感謝您提供答案。

我有一個服務公開一個異步方法,該方法將請求發送到一些api。 此方法在后面的Webforms代碼中使用。 我知道ASP.NET一次只允許一個線程執行,所以調用Task.Wait()會導致死鎖,因為等待的任務在完成后由於上下文線程被阻塞而無法繼續執行。

但是,根據我的理解(從閱讀本博客開始 ),在等待的任務上調用ConfigureAwait(false)會使任務改為在線程池線程上運行,因此可以恢復在上下文線程上的執行。 我仍然從下面的代碼中陷入僵局。 為什么是這樣?

protected void Activate(object sender, CommandEventArgs e)
{
    var someID = int.Parse((string) e.CommandArgument);
    DoAsyncThingWithID(someID).Wait();
}

private async Task DoAsyncThingWithID(int ID)
{
    try
    {
        await new SomeService()
            .DoSomeAsyncWork(ID)
            .ConfigureAwait(false);
    }
    catch (AppropriateException e)
    {
        DealWithIt();
    }
}

可能需要注意:DoSomeAsyncWork(int)在其“下方”具有更多異步方法。 在底部的右邊是一個api包裝對象(負責發送HTTP請求),該對象的方法不是異步的,而是通過Task.Run(() => api.SendThingy());調用的Task.Run(() => api.SendThingy());

這可能是問題嗎?

但是,據我的理解(從閱讀本博客開始),在等待的任務上調用ConfigureAwait(false)會使任務改為在線程池線程上運行,因此可以恢復在上下文線程上的執行。

實際上,使用ConfigureAwait(false)意味着當前方法繼續並不關心它在哪個上下文中執行-在大多數情況下,這意味着它將在線程池線程上繼續執行。

因此, DoSomeAsyncWork仍將在ASP.NET上下文中運行。 因此,僅一個ConfigureAwait(false)是不夠的。 您必須確保DoSomeAsyncWork也使用ConfigureAwait(false)以及它調用的所有異步方法,以及它們調用的所有異步方法,等等,包括Microsoft或第三方庫方法。

這就是為什么我建議一開始就不阻止的原因。 如果絕對必要ConfigureAwait(false) hack只是嘗試解決它的方法之一。

現在,我已經通過簡單地將按鈕單擊處理程序標記為async void並等待任務來解決了該問題。 我認為WebForms不能以任何方式處理async ,除非與RegisterAsyncTask 雖然這解決了我的問題,但我仍然對原始代碼為何會死鎖感到興趣,因為它與我目前對異步C#代碼如何工作的理解背道而馳,因此,我們仍然歡迎進一步的回答。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM