2017-07-27 73 views
-3

從我的方法拿走await關鍵字時,我比較性能,以及它給我過15倍更好的性能。異步取15倍長於同步

以下方法執行好得多:

private static async Task<HttpResponseMessage> AwaitResponse(HttpRequest proxy) 
{ 
    foreach (var header in proxy.Request.Headers) 
    { 
     Client.Instance.DefaultRequestHeaders.Add(header.Key, header.Value); 
    } 

    var response = Client.Instance.SendAsync(proxy.Request).Result; 
    return response; 
} 

不止這一個:

private static async Task<HttpResponseMessage> AwaitResponse(HttpRequest proxy) 
{ 
    foreach (var header in proxy.Request.Headers) 
    { 
     Client.Instance.DefaultRequestHeaders.Add(header.Key, header.Value); 
    } 

    var response = Client.Instance.SendAsync(proxy.Request); 
    return await response; 
} 

通知我如何打電話。結果在方法的第一個版本。

這究竟是爲什麼?爲什麼會有如此巨大的性能損失?

請注意,Client僅僅是HttpClient一個靜態實例。

+1

1.說「x15增加」,但你沒有指定數字。這是10ms vs 150ms,還是200ms vs. 3000ms?這很重要。 2.是否有許多其他併發請求在同一時間執行類似的操作? 'await'放棄線程,並且必須將上下文編組回到它返回時的位置。如果有很多請求,你的線程池可能會很忙。 3.在'await'中添加'ConfigureAwait(false)'是否改變行爲? –

+0

它會從1000到12000毫秒 –

+0

沒有其他併發請求 –

回答

4

當使用await,代碼的執行上下文被掛起,直到異步方法的回報。默認情況下,await試圖恢復新線程,它起源於這有時會影響性能,因爲CLR需要等待原來的SynchronizationContext元帥回傳入同步上下文。一般來說,除非你有特定的需求返回到你留下的同一個線程上下文(比如在客戶端應用程序中,返回到UI線程),否則最好添加ConfigureAwait(false)並繼續執行任意線程。

4

鑑於您沒有實際使用片段中任何內容的響應,因此不需要實際使用異步/等待或致電.Result。您可以返回Task以便呼叫者等待或在更高級別呼叫.Result

private static Task<HttpResponseMessage> AwaitResponse(HttpRequest proxy) { 
    foreach (var header in proxy.Request.Headers) { 
     Client.Instance.DefaultRequestHeaders.Add(header.Key, header.Value); 
    } 
    return Client.Instance.SendAsync(proxy.Request); 
} 

我也建議審查

Async/Await - Best Practices in Asynchronous Programming從斯蒂芬·克利

問題不是左右混合阻塞和異步代碼,同時也對如何以及何時ConfigureAwait(false)時,你可以

+0

這是一個很好的觀點,所以你在說「如果我在我的應用程序中沒有使用async/await,目的是什麼?相反,讓客戶端做到這一點?」 ?? –

+0

不,只需要關鍵字async/await,您需要保留上下文以進行進一步處理。例如,你需要在調用'SendAsync'之後在結果裏面做一些事情,然後'async/await'將被保證。然而,在這種情況下你並不需要這麼做,所以在這種方法中不需要使用'async/await'。 – Nkosi

+1

儘管您可以忽略異步/等待並簡單地從您自己的異步函數中返回內部任務,但它並不總是最佳選擇。這是斯蒂芬克萊裏,再次,[利弊](https://blog.stephencleary.com/2016/12/eliding-async-await.html)。簡而言之,如果存在異常,直接返回內部任務會使您的功能不會顯示在堆棧跟蹤中。 –