1

我有一個控制檯應用程序,用戶在其中輸入一個菜單選項(1-5),執行一些功能並輸出結果。C# - 執行200個http獲取請求並輸出結果

其中一項功能是對某個url執行200個http get請求,將所有結果返回,對它們執行一些操作並輸出給用戶。

這是我當前的代碼:

 Parallel.For(0, 200, i => 
     { 
      String[] words = webApi.getSplittedClassName(); 
      for (int j = 0; j < words.Length; j++) 
      { 
       wordsList.Add(words[j]); 
      } 

     }); 

getSplittedClassName

public string[] getSplittedClassName() 
    { 
     HttpResponseMessage response = null; 
     try 
     { 
      response = httpClient.GetAsync(url).Result; 
     } 
     catch (WebException e) 
     { 
      return null; 
     } 
     return parser.breakdownClassName(response); 
    } 

現在,由於用戶輸入選項的數值,程序executess所需的功能,然後我把輸出,我認爲沒有在異步做http工作的意義,所以它的所有同步。

問題是,它花了很多時間來做請求,大約30-40秒..是否有意義?

基本上有3個功能:做1個請求,做3個請求和200個請求。

做200個請求並等待所有結果的最佳選擇是什麼?它應該是同步的,就像我只發出一個請求一樣?

感謝

+1

爲什麼你想要做200個GET請求?你能否將請求合併到一個服務器上,然後在服務器上進行處理,然後將你想要輸出的內容返回給用戶? – DHP

+0

沒有,我不能,它的一部分練習..我需要做200個請求,並在最佳實踐中,工作的結果和輸出。 –

+0

爲什麼你選擇不這樣做異步?是否有一個理由,它應該是同步的? – StriplingWarrior

回答

2

Parallel.For()傾向於假設你的操作大多是CPU密集型的,所以它會使用並行度的多數民衆贊成調整到你的機器有多少CPU內核了。但HTTP請求往往是IO限制的,所以大部分時間都花在等待目標機器發回信息給你。

這意味着這是使用異步處理的好機會。嘗試是這樣的:

public async Task<string[]> getSplittedClassName() 
{ 
    HttpResponseMessage response = await httpClient.GetAsync(url); 
    return parser.breakdownClassName(response); 
} 

這:

var classNameTasks = Enumerable.Range(1, 200) 
     .Select(i => webApi.getSplittedClassName()) 
     .ToArray(); 
    wordList.AddRange(
     Task.WhenAll(classNameTasks).Result 
      .SelectMany(g => g)); 

說明:

  1. getSplittedClassName()異步使,而不是得到它所需要的東西同步,然後返回結果,它立即返回一個Task<>,當結果可用時將會完成。
  2. 我刪除了吃所有異常的代碼,因爲這通常是一種不好的做法。如果這裏出現異常情況,您應該考慮一下您真正想做的事情:是否應該重試請求?只是讓異常被拋出?忽略這樣的問題通常是個壞主意。
  3. Task.WhenAll()將返回一個Task<>,它將返回給定任務的所有結果。您可以同步等待所有這些任務完成,然後將它們全部作爲批次添加到wordList。這是線程安全的,因爲所有項目都會在單個線程中添加到wordList,而您的原始代碼有多個線程可能嘗試同時向wordList添加值。

此外,我假設這只是一項家庭作業,但如果這是一個真實世界的場景,事實上,您同時對同一個URL做200個GET請求將是一個大紅旗。

+0

感謝您的答案。這是一項家庭作業,但完成所有請求仍需大約40-50秒。這是正常的嗎?另外,1個請求和3個請求的選項應該同步完成嗎? –

+0

@OfekAgmon:很難說這是否正常,因爲我不知道目標服務器是如何設置的。請求返回通常需要多長時間?目標服務器在處理併發請求時會看到多少性能下降?我沒有看到任何理由以任何不同的方式處理1或3個請求:HTTP請求本質上是一種異步操作,所以從性能的角度來看,沒有強制性的理由來強制您的代碼同步運行。 – StriplingWarrior

+0

好的,非常感謝。還有一個小問題 - 我把你發佈的兩行代碼(Enumerable.Range)的簽名設置爲「public async Task execFeature」,並且有警告說我沒有使用「await」和因此該方法將同步運行。是甚至相關?因爲我將所有的方法放在調用異步的鏈中,並返回某種類型的Task,並且program.cs中的第一個調用是featureService.startService()。Wait()。它應該是這樣嗎?謝謝100萬 –