2013-01-21 23 views
123

我正在構建一個類庫來與API進行交互。我需要調用API並處理XML響應。我可以看到使用HttpClient進行異步連接的好處,但是我所做的是純粹的同步,所以看不到比HttWebRequests更多的好處。爲什麼要使用HttpClient進行同步連接

如果任何人都可以擺脫任何光線,我將不勝感激。爲了它,我不是一個使用新技術的人。

+2

我不想告訴你,而是通過HTTP調用從來都不是純粹的同步因如何在Windows內部網絡工作(又名完成端口)。 – TomTom

回答

236

但我在做什麼是純粹的同步

你可以使用HttpClient同步請求就好了:

using (var client = new HttpClient()) 
{ 
    var response = client.GetAsync("http://google.com").Result; 

    if (response.IsSuccessStatusCode) 
    { 
     var responseContent = response.Content; 

     // by calling .Result you are synchronously reading the result 
     string responseString = responseContent.ReadAsStringAsync().Result; 

     Console.WriteLine(responseString); 
    } 
} 

至於爲什麼你應該使用的HttpClient在WebRequest的來講,好吧,HttpClient是該塊上的新成員,並且可以包含對舊客戶端的改進。

+12

不同步使用異步方法可能會阻塞你的UI線程嗎?你可能想考慮一些像'string responseString = Task.Run(()=> responseContent.ReadAsStringAsync())。Result;'而是如果你必須使這個同步。 – earthling

+0

@earthling,是的,我的解決方案將阻止UI線程。但是我不明白的是你在這方面有什麼不同?您正在調用在主UI線程上啓動的任務上的'.Result'。不會阻止這個線程? –

+1

在你的情況下,任務在有限數量的可用線程上下文中運行。如果這是UI線程,則該數字= 1.使用Task.Run從ThreadPool調用「任務」。至少這是我理解這一切的作品。當然,我仍然在學習,但是我只是在需要同步運行的自定義'IValueConverter'中實現了它,並且它似乎可以工作。 – earthling

6

如果你正在建設一個類庫,那麼也許您的圖書館的用戶想使用異步您的圖書館。我認爲那是最重要的原因。

你也不知道你的圖書館將如何被使用。也許用戶會處理大量的請求,並且這樣做會異步地執行,這將幫助它更快更高效地執行。

如果你可以簡單地做到這一點,儘量不要讓你的庫的用戶負擔,試圖使流程異步時,你可以爲他們照顧它。

我不會使用異步版本的唯一原因是,如果我試圖支持尚不具有內置的異步支持.NET的舊版本。

+0

我明白了,所以要讓類庫異步,並允許系統的用戶決定是使用異步還是使用await並同步使用它? – Ketchup

+0

erm,通過返回控制給調用者等待有助於使某些調用異步。 –

15

的一個主要的原因我使用的HttpClient是因爲當一個URL返回一個404不會拋出異常。

21

我會重新迭代唐尼五答案,Josh的

「我不會用異步版本的唯一原因是,如果我試圖 支持.NET,做的舊版本尚未在異步支持中構建 「。

(並給予好評,如果我有名聲。)

我不記得上一次如果有的話,我很感激的事實HttpWebRequest的投擲例外狀態碼> = 400要解決這些問題需要立即捕獲異常,並將它們映射到代碼中的一些非異常響應機制......本身就是無聊,乏味且容易出錯的。無論是與數據庫進行通信還是實現定製的Web代理,它的「幾乎」總是可取的,即Http驅動程序只是告訴你的應用程序代碼返回的內容,並由你決定如何行事。

因此HttpClient的是優選的。

+0

我很驚訝'HttpClient'本身就是'HttpWebRequest'的封裝(實際上,內部捕獲這些'WebException'對象併爲你轉換爲'HttpResponseMessage')。我原以爲從零開始構建新的客戶端會更容易。 – Dai

+0

有很多很好的理由,例如不想重寫整個代碼庫,只是爲了一個甚至不是性能關鍵的非常低級別的http調用(但會引入一百萬個異步)。 – FrankyBoy

2

在我的情況下,接受的答案是行不通的。我從一個沒有異步動作的MVC應用程序調用API。

這是我如何設法使其工作:

private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default); 
public static T RunSync<T>(Func<Task<T>> func) 
    {   
     CultureInfo cultureUi = CultureInfo.CurrentUICulture; 
     CultureInfo culture = CultureInfo.CurrentCulture; 
     return _myTaskFactory.StartNew<Task<T>>(delegate 
     { 
      Thread.CurrentThread.CurrentCulture = culture; 
      Thread.CurrentThread.CurrentUICulture = cultureUi; 
      return func(); 
     }).Unwrap<T>().GetAwaiter().GetResult(); 
    } 

然後我把它叫做是這樣的:

Helper.RunSync(new Func<Task<ReturnTypeGoesHere>>(async() => await AsyncCallGoesHere(myparameter))); 
相關問題