簡體   English   中英

同步使用漂亮的.net 4.5 HttpClient的最佳方法

[英]best way to use the nice .net 4.5 HttpClient synchronously

我喜歡新的System.Net.Http.HttpClient類。 它有一個很好的簡單API,它不會拋出正常的錯誤。 但它只是異步。

我需要代碼(深入服務器內)

foo();
bar();
// compute stuff
var x = GetThingFromOtherServerViaHttp();
// compute more stuff
wiz(x);

經典的順序同步代碼。 我看到了幾個類似的問題,但實際上從未真正說過“做這個”。 我在看

client.PostAsync.Wait()

世界尖叫'不要這樣做'。 怎么樣:

client.PostAsync.Result()

這不只是偽裝等待?

最后,我最終傳入一個處理結果的lambda回調,然后喚醒顯式等待EventWaitHandle的調用線程。 很多管道。 有沒有更簡單的東西或者我只是回到使用舊的http客戶端

編輯:進一步閱讀后,我懷疑這段代碼與Wait和Result有相同的問題,它只是一個更長的死鎖

編輯:我有MS PM最近向我確認有一個任務'可能需要> X ms(我忘了​​X)的任何API必須是異步',許多PM將此解釋為'僅異步'(不清楚這是什么旨在)。 因此Document DB api只是異步。

來自http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx

return Task.Run(() => Client.PostAsync()).Result;

@Noseratio - 當然我擔心死鎖:-)

如果你在具有同步上下文的線程上,你只會擔心死鎖。

這通常是UI應用程序的主線程(客戶端),或隨機ASP.NET線程處理HTTP請求(服務器端)。 在任何一種情況下,你真的不應該阻止它。

接受的答案可能有助於緩解死鎖,但是這樣的阻塞仍然會影響UI應用程序的最終用戶體驗(UI會被凍結),或服務器端應用程序的可伸縮性(線程浪費了阻塞,而它可能是提供另一個請求)。 只是不要阻止並一直使用async/await

您提到“服務器內部深處”,但沒有提供有關服務器端應用程序的詳細信息。 大多數現代服務器端框架都具有良好的async/await管道,因此它不應該是一個問題。

更新以解決評論:

我仍然不喜歡在不同地方編寫的相同代碼會死鎖的事實。 我希望在一個容易出現死鎖的環境中等待調用

這不是async/await特別問題,而是一般的同步上下文概念,當它與阻塞代碼一起使用時。 簡而言之,這就是僵局:

private void Form1_Load(object sender, EventArgs e)
{
    var mre = new System.Threading.ManualResetEvent(initialState: false);
    System.Threading.SynchronizationContext.Current.Post(_ => 
        mre.Set(), null);
    mre.WaitOne();
    MessageBox.Show("We never get here");
}

從理論上講,有可能嘗試通過檢查Thread.ThreadState == System.Threading.ThreadState.WaitSleepJoin來緩解SynchronizationContext.Post潛在的死鎖。 然而,這不是100%可靠的解決方案。

有爭議的我會說System.Net.Http.HttpClient可能只能使用.Result

微軟應該遵循他們自己的建議並在該庫中一直使用.ConfigureAwait(false) 參考來源暗示:

https://github.com/dotnet/corefx/blob/master/src/System.Net.Http/src/System/Net/Http/HttpClient.cs

為什么要承擔風險? 因為它應該比Task.Run(() => Client.PostAsync()).Result

我不相信許多(任何?)其他庫安全編碼,並期待看到是否有人反對我的答案或更好,但證明我錯了。

暫無
暫無

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

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