2017-03-04 28 views
0

我有5個URL,我想爲每個請求做一個Http請求,並等待有條件的第一個響應。獲得並行的第一個Http響應

List<string> urls; // url1, url2, ...... 

ParallelLoopResult result = Parallel.ForEach(urls, url=> GetTimeSlot(url)); 

private string GetTimeSlot(string url) 
{ 
    HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url); 

    HttpWebResponse response = (HttpWebResponse)wr.GetResponse(); 
     string responseString = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(response.CharacterSet)).ReadToEnd(); 
     if (responseString.Length < 6) 
      return ""; //PARALEL RESUME 
     else 
      return responseString; //PARALEL ENDS 
} 

我只需要第一個響應。並行還是有可能嗎?還有更好的方法嗎?謝謝。

回答

2

Parallel.ForEach可以很好地用於您的用例。只需使用取消令牌來停止所有其他正在運行的任務。

static void Main(string[] args) 
    { 
     var cts = new CancellationTokenSource(); 
     var _lock = new Object(); 
     var po = new ParallelOptions(); 
     po.CancellationToken = cts.Token; 
     po.MaxDegreeOfParallelism = System.Environment.ProcessorCount; 
     var listOfUrls = new List<string>() { "url1", "url2" }; 
     var responsResult = ""; 
     try 
     { 
      Parallel.ForEach(listOfUrls, po, (url) => 
      { 
       po.CancellationToken.ThrowIfCancellationRequested(); 

       HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url); 

       HttpWebResponse response = (HttpWebResponse)wr.GetResponse(); 
       string responseString = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(response.CharacterSet)).ReadToEnd(); 

       lock (_lock) 
       { 
        if (responseString.Length > 6) 
        { 
         responsResult = responseString; 
         cts.Cancel(); 
        }       
       }   

      }); 
     } 
     catch (OperationCanceledException e) 
     { 
      //cancellation was requested 
     } 
     finally 
     { 
      cts.Dispose(); 
     } 
    } 
+0

使用鎖,使其確保沒有其他線程正在更新的結果。當你調用cts.Cancel()時拋出的OperationCanceledException是你期望的。如果它是另一個異常,但是OperationCanceledException表示WebRequest出錯了。 – Dynamikus

+0

非常感謝你兄弟。有效!!我要測試'lock'。 –

+0

np祝你好運!!! – Dynamikus

1

您可以使用PLINQ:

string firstResponse = urls 
    .AsParallel() 
    .Select(url => GetTimeSlot(url)) 
    .FirstOrDefault(r => ! string.IsNullOrEmpty(r))     
    ; 
+0

謝謝@亨克。當我得到第一個響應時是否取消操作? –

+0

它不會取消任何內容,但它不會啓動新的內容。無論已經運行什麼都會完成。徒然。 –

相關問題